typescript - 在 TypeScript 中动态提取类型

标签 typescript typescript-typings mapped-types

我正在尝试根据某些标志将一种类型动态映射到另一种类型,这可能会产生可选字段。

type Constraint = {
  required: boolean,
  callback: () => any,
}

type Schema = Record<string, Constraint>;

const mySchema: Schema = {
  bar: {
    required: true,
    callback: () => 1
  },
  foo: {
    required: false,
    callback: () => true
  }
}

type MapSchemaToOutput<T extends Schema> = {
  [K in keyof T as T[K]['required'] extends true ? K : never]: ReturnType<T[K]['callback']>
} & {
  [K in keyof T as T[K]['required'] extends false ? K : never]?: ReturnType<T[K]['callback']>
}

type Output = MapSchemaToOutput<typeof mySchema>;

最终目标是让输出相等:

{
  bar: number,
  foo?: boolean
}

我知道我可以手动进行映射,有兴趣知道这是否可以动态完成。

最佳答案

您的方法按原样工作,只需进行一处更改。

问题是 : Schema注释是“丢弃类型信息”:

const mySchema: Schema = {
   //...
};

有了这个注释,TS 只记得 mySchemaRecord<string, Constraint>不是任何对象的具体结构


一个修复是 as const :

const mySchema = {
    //...
} as const;

这保留了对象内的文字类型。然而,mySchema的内容不再有任何限制。 ,以及定义 mySchema 的任何错误必须通过使用来捕获,而不是在定义时捕获。


更好的解决方法是使用辅助函数引入约束,而不直接注释类型:

function buildSchema<T extends Schema>(schema: T) { return schema; }

const mySchema = buildSchema({
   //...
});

由于<T extends Schema>约束,如果架构对象与指定类型不匹配,TS 将像以前一样引发错误。

但与注释对象的类型不同,此函数返回的类型与传递给函数的文字对象相同:因此不会丢失任何类型信息。

With this change, the rest of the types work as expected

关于typescript - 在 TypeScript 中动态提取类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66496550/

相关文章:

Typescript 将并集转换为交集

typescript - 如何在 Typescript 中将接口(interface)转换为映射类型

typescript - TypeScript 映射类型的乐趣和挫折

angular - NGRX - 每次效果后运行函数

angular - 如何将 jwt-decode 类型定义导入 Typescript (Ionic 2)

typescript 和解构数组

typescript - 如何在不导入的情况下包含特定文件夹中文件的 typescript 文件?

typescript - 接口(interface)不能扩展条件类型中的映射类型

javascript - 不是常见范围的函数错误

html - 路由 Angular 4/5 隐藏组件