如何将一种泛型类型的结构复制到 TypeScript 中的另一种泛型?

Posted

技术标签:

【中文标题】如何将一种泛型类型的结构复制到 TypeScript 中的另一种泛型?【英文标题】:How to copy the structure of one generic type to another generic in TypeScript? 【发布时间】:2021-09-07 08:05:07 【问题描述】:

假设我们有以下输入类型:

interface Input 
    name: string;
    heightCm: number;
    dob: Date;

我想写一个函数,可以根据这个输入产生以下输出类型:

interface Output 
    name: boolean;
    heightCm: boolean;
    dob: boolean;

换句话说,一个复制输入结构并将该结构作为输出返回的函数,将所有值设置为布尔值。

函数签名看起来像这样:

interface GenericMap<T> 
    [key: string]: T;


type InputToOutput<In, Out extends GenericMap<boolean>> = (input: In) => Out;

如果Input属性的类型最初是字符串,则将该属性标记为true,否则标记为false

例如该函数将根据上面的Input 产生以下结果:


    name: true,
    heightCm: false,
    dob: false

但最重要的是,它需要是类型安全的,这样我才能在结果对象上接收智能感知。

帮助不胜感激!

【问题讨论】:

我不确定您是否只是在寻找mapped types,或者您真的想要具有尽可能强类型的完整实现,例如this。该代码是否满足您的需求,还是您想要别的东西? 【参考方案1】:

我想你只是想要一个将每个属性的类型设置为布尔值的映射类型?

type GenericMap<T> = 
    [K in keyof T]: boolean

你会使用喜欢的:

interface Input 
    name: string;
    heightCm: number;
    dob: Date;


type Output = GenericMap<Input>
// Output is
// 
//    name: boolean;
//    heightCm: boolean;
//    dob: boolean;
// 

Playground


作为一个(潜在的)改进,您甚至可以检查此类型别名中的string 并返回truefalse,而不是boolean

type GenericMap<T> = 
    [K in keyof T]: T[K] extends string ? true : false

这会产生这种类型:

type Output = GenericMap<Input>
// 
//    name: true;
//    heightCm: false;
//    dob: false;
// 

【讨论】:

您好,我收到一个错误,即在 GenericMap 中使用它时找不到名称“keyof”,如您所示。但是,这可行:type K&lt;T&gt; = keyof GenericMap&lt;T&gt;; 但是我仍然不能将其用作 GenericMap 的键签名。有任何想法吗?我在 Typescript @4.3 问题是我使用interface 来定义GenericMap。它必须是 type 才能在密钥签名中使用“keyof”(无论出于何种原因)【参考方案2】:

我已经实现了你想要的:

interface Input 
    name: string;
    heightCm: number;
    dob: Date;


type Out<In> =  [key in keyof In]: In[key] extends string ? true : false 
type InputToOutput<In> = (input: In) => Out<In>;
type Output = Out<Input>;

const clone: InputToOutput<Input> = input => output;

const input: Input =  name: 'foo', heightCm: 3, dob: new Date ;

const output: Output = clone(input);

当悬停Output 类型时会给出以下输出:

const output: 
    name: true;
    heightCm: false;
    dob: false;

【讨论】:

以上是关于如何将一种泛型类型的结构复制到 TypeScript 中的另一种泛型?的主要内容,如果未能解决你的问题,请参考以下文章

使用多种泛型类型在 Java 中实现抽象泛型方法

将一种结构复制到另一种结构

受其他泛型参数约束的泛型参数

C# 泛型

Kotlin - 推断两个泛型参数之一的类型

将一种类型的 unique_ptr 复制到另一种类型的工作原理