有没有办法获取打字稿对象的所有必需属性

adm*_*r86 1 reflection typescript

有没有一种方法可以获取打字稿界面或对象的所有必需属性。类似Object.getOwnPropertyDescriptors(myObject)keyof T带有信息属性的东西是必需的/可选的

Gab*_*ani 11

如果 2022 年有人仍在寻找答案,这对我有用:

export type GetOptionalKeys<T> = {[K in keyof T as (undefined extends T[K] ? K : never)]: T[K]}

export type GetRequiredKeys<T> = {[K in keyof T as (undefined extends T[K] ? never : K)]: T[K]}
Run Code Online (Sandbox Code Playgroud)

资源:https ://www.typescriptlang.org/docs/handbook/2/mapped-types.html#key-remapping-via-as


jca*_*alz 5

在运行时这是不可能的,因为属性的必要性/可选性仅存在于TypeScript类型系统中,而在代码实际运行时已被擦除。您可以通过装饰器等添加自己的运行时信息,但是为此,您需要修改生成类和对象的实际代码。因此,不可能获得给定对象或构造函数的必需属性名称的数组。


在设计时它可能提取的类型的所需的/可选的键,作为的一个亚型keyof T。该解决方案依赖于条件类型和以下事实:空对象类型{}被认为可分配给弱类型(没有必需属性的类型)。像这样:

type RequiredKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? never : K }[keyof T];
type OptionalKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? K : never }[keyof T];
Run Code Online (Sandbox Code Playgroud)

以及示例用法:

interface SomeType {
  required: string;
  optional?: number;
  requiredButPossiblyUndefined: boolean | undefined;
}

type SomeTypeRequiredKeys = RequiredKeys<SomeType>; 
// type SomeTypeRequiredKeys = "required" | "requiredButPossiblyUndefined" 

type SomeTypeOptionalKeys = OptionalKeys<SomeType>; 
// type SomeTypeOptionalKeys = "optional" 
Run Code Online (Sandbox Code Playgroud)

带有索引签名的类型不能很好地发挥作用:

interface SomeType {
  required: string;
  optional?: number;
  requiredButPossiblyUndefined: boolean | undefined;
  [k: string]: unknown; // index signature
} 

type SomeTypeRequiredKeys = RequiredKeys<SomeType>;
// type SomeTypeRequiredKeys = never 

type SomeTypeOptionalKeys = OptionalKeys<SomeType>;
// type SomeTypeOptionalKeys = string 
Run Code Online (Sandbox Code Playgroud)

不知道您的用例是否关心可索引类型。如果是这样,那么存在一种更复杂的解决方案,该解决方案通过首先提取已知文字键然后检查是否需要/可选来解决该问题:

type RequiredLiteralKeys<T> = { [K in keyof T]-?:
  string extends K ? never : number extends K ? never : {} extends Pick<T, K> ? never : K
} extends { [_ in keyof T]-?: infer U } ? U extends keyof T ? U : never : never;

type OptionalLiteralKeys<T> = { [K in keyof T]-?:
  string extends K ? never : number extends K ? never : {} extends Pick<T, K> ? K : never
} extends { [_ in keyof T]-?: infer U } ? U extends keyof T ? U : never : never;

type IndexKeys<T> = string extends keyof T ? string : number extends keyof T ? number : never;
Run Code Online (Sandbox Code Playgroud)

结果是:

type SomeTypeRequiredKeys = RequiredLiteralKeys<SomeType>;
// type SomeTypeRequiredKeys = "required" | "requiredButPossiblyUndefined" 

type SomeTypeOptionalKeys = OptionalLiteralKeys<SomeType>; 
// type SomeTypeOptionalKeys = "optional" 

type SomeTypeIndexKeys = IndexKeys<SomeType>;
// type SomeTypeIndexKeys = string 
Run Code Online (Sandbox Code Playgroud)

希望能有所帮助。祝好运!

  • 为什么需要`-?`?在我看来,从每个键中删除可选标签不会影响最终结果?我缺少什么? (2认同)