TypeScript如何实现字段数组同时用于类型推导与接口传参
实现方法
首先可以先优化你现有的泛型函数定义,去掉冗余的泛型参数,同时适配常量类型推导:
interface Foo { A?: string; B?: number; C?: boolean; D?: string[]; E?: number[]; } // TS 4.9及以上版本可以用const类型参数,调用时无需手动加as const declare function getFoo<const K extends keyof Foo>(fields: readonly K[]): Pick<Foo, K>; // 低版本TS可以去掉const修饰,调用时给数组加as const即可 // declare function getFoo<K extends keyof Foo>(fields: readonly K[]): Pick<Foo, K>;
不需要先声明接收返回值的变量再通过typeof取类型,根据使用场景选下面两种方式即可:
- 不需要单独复用精简类型的场景:直接调用函数即可,TS会自动推导出返回值的精确类型,访问不存在的属性时会直接报类型错误:
// TS自动推导myFoo类型为{ A?: string; C?: boolean } const myFoo = getFoo(['A', 'C']); - 需要单独复用精简类型、或者抽离fields数组做复用的场景:先把fields声明为加了
as const的常量,直接通过数组元素类型推导返回类型,无需调用函数:const myFooFields = ['A', 'C'] as const; // 直接推导得到精简类型 type MyFoo = Pick<Foo, typeof myFooFields[number]>; // 调用时直接传入抽离的fields常量 const myFoo = getFoo(myFooFields);
你之前用
ReturnType<typeof getFoo>拿不到目标类型的原因是:ReturnType操作泛型函数时,如果没有传入具体的泛型参数,TS会按照泛型的约束范围做宽泛推导,此时K会被推导为keyof Foo也就是所有键的联合类型,最终自然得到完整的Foo类型。泛型的具体类型参数只有在函数实际传入参数调用时才会被确定,单独引用函数本身的类型无法得到特定入参对应的返回值类型。
内容的提问来源于stack exchange,提问作者Tim Schmidt
相关产品推荐
相关产品推荐

