Typescript 映射类型未生成正确的输出

huangapple go评论76阅读模式
英文:

Typescript mapped types not generating correct output

问题

我正在处理一个项目,我希望允许用户选择从特定类型中获取特定字段。给定以下类型:

type DataType = {
  field1: number;
  field2: string;
  field3?: {
    subField1: number;
    subField2: string;
  };
  field4?: number[];
};

我想将这个类型转换为以下类型:

type DataTypeFlags = {
  field1?: boolean;
  field2?: boolean;
  field3?: {
    subField1?: boolean;
    subField2?: boolean;
  };
  field4?: boolean;
};

我已经提出了以下解决方案,它大部分工作正常,但如果原始类型中的字段之一具有数组字段,它会出现问题:

type Flags<T extends Record<string, any>> = {
  [K in keyof T]: T[K] extends Record<string, any> | undefined ? Flags<T[K]> : boolean;
};

type DataTypeFlags = Flags<DataType>;
// 输出:
// {
//   field1?: boolean; | undefined  // 正常
//   field2?: boolean; | undefined  // 正常
//   field3?: {
//     subField1?: boolean | undefined; // 正常
//     subField2?: boolean | undefined; // 正常
//   } | undefined;
//   field4?: (boolean | undefined)[] | undefined; // 出现问题
// }

为什么我的 Flags 类型在目前的状态下不起作用?是否有解决方法,还是这是 TypeScript 的限制?

英文:

I'm working on a project where I want to allow the user to choose specific fields to get from a specific type. Given the following type:

type DataType = {
  field1: number;
  field2: string;
  field3?: {
    subField1: number;
    subField2: string;
  };
  field4?: number[];
};

I want to convert this type to the following type:

type DataTypeFlags = {
  field1?: boolean;
  field2?: boolean;
  field3?: {
    subField1?: boolean;
    subField2?: boolean;
  };
  field4?: boolean;
};

I have come up with the following which mostly works well, but breaks if one of the fields from the original type has a field that is an array:

type Flags&lt;T extends Record&lt;string, any&gt;&gt; = {
  [K in keyof T]: T[K] extends Record&lt;string, any&gt; | undefined ? Flags&lt;T[K]&gt; : boolean;
};

type DataTypeFlags = Flags&lt;DataType&gt;;
// outputs:
// {
//   field1?: boolean; | undefined  // good
//   field2?: boolean; | undefined  // good
//   field3?: {
//     subField1?: boolean | undefined; // good
//     subField2?: boolean | undefined; // good
//   } | undefined;
//   field4?: (boolean | undefined)[] | undefined; // breaks here
// }

Why does my Flags type not work in the state that it's in? Is there a solution to this or is this a limitation of Typescript?

答案1

得分: 2

代码部分不提供翻译。

英文:

It seems that the problem here is the use of optional types.
One possible solution is to use NonNullable wrappers to exclude undefined from the given type. Here's an example:

type DataType = {
  field1: number;
  field2: string;
  field3?: {
    subField1: number;
    subField2: string;
  };
  field4?: number[];
};

type Flages&lt;T extends Record&lt;string, unknown&gt;&gt; = {
  [P in keyof T]+?: NonNullable&lt;T[P]&gt; extends Record&lt;string, unknown&gt; ? Flages&lt;NonNullable&lt;T[P]&gt;&gt; : boolean
}


const example: Flages&lt;DataType&gt; = {
  field1: false,
  field3: {
    subField1: false
  },
  field4: true
}

PS +? modifier will explicitly make a property optional

TS Playground

答案2

得分: 0

以下是代码部分的翻译:

type Flags<T extends Record<string, any>> = {
  [K in keyof T]: T[K] extends (any[]|undefined) ? boolean : T[K] extends Record<string, any> | undefined ? Flags<NonNullable<T[K]>> : boolean;
};

请注意,这是 TypeScript 代码,用于定义一个 Flags 类型。如果你需要进一步的解释或有其他问题,请随时提出。

英文:

What about just handling the use case of arrays ?

type Flags&lt;T extends Record&lt;string, any&gt;&gt; = {
  [K in keyof T]: T[K] extends (any[]|undefined) ? boolean : T[K] extends Record&lt;string, any&gt; | undefined ? Flags&lt;NonNullable&lt;T[K]&gt;&gt; : boolean;
};

Playground

huangapple
  • 本文由 发表于 2023年2月18日 19:52:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/75493145.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定