如何从打字稿中的类中创建不包括实例方法的类型?

HHK*_*HHK 16 typescript typescript-generics

给定一个包含属性和方法的类,我想派生一个只包含其属性的类型。

例如,如果我定义一个类如下:

class MyObject {

  constructor(public prop1: string, public prop2: number) {}

  instanceMethod() { ... }
}
Run Code Online (Sandbox Code Playgroud)

我想要一个类型,MyObjectConstructor比如这样:

type MyObjectConstructor = {
  prop1: string;
  prop2: number;
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用内置类型Pick并按名称手动选择我想要的键,但我不想重复所有键,并且每次向我的类添加新属性时都必须更改它们。

有没有办法定义ConstructorType<T>只返回 typescript 中类的属性的泛型类型?

HHK*_*HHK 19

由于这篇文章,我找到了一种排除与给定类型匹配的所有属性的方法:https : //medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c

我做了一些改编,但这里是细节:

// 1 Transform the type to flag all the undesired keys as 'never'
type FlagExcludedType<Base, Type> = { [Key in keyof Base]: Base[Key] extends Type ? never : Key };
    
// 2 Get the keys that are not flagged as 'never'
type AllowedNames<Base, Type> = FlagExcludedType<Base, Type>[keyof Base];
    
// 3 Use this with a simple Pick to get the right interface, excluding the undesired type
type OmitType<Base, Type> = Pick<Base, AllowedNames<Base, Type>>;
    
// 4 Exclude the Function type to only get properties
type ConstructorType<T> = OmitType<T, Function>;
Run Code Online (Sandbox Code Playgroud)

尝试一下

可能有一种更简单的方法,我尝试使用ConstructorParameters并定义构造函数签名,但没有结果。

更新

在这里浏览打字稿文档时发现了一个等价物:https : //www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types

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

由于省略的类型不是通用的,所以它不那么冗长,但它是相同的想法。

  • 这个答案的问题在于,它认为它排除了方法,但它也排除了函数属性,这是有问题的。不幸的是,Typescript 目前似乎没有提供区分方法和函数属性的方法,尽管 VSCode 悬停提示实际上对它们进行了区分。 (3认同)

far*_*eri 16

从 Typescript 4.1 版开始,您可以执行以下操作:

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


Sha*_*tin 5

给定一个包含属性和方法的类,我想派生一个仅包含其属性的类型。

从您的示例来看,您似乎希望结果仅包含字段(而不是仅包含属性)。这是一种从对象或类实例中挑选字段的类型。

type DataPropertyNames<T> = {
  [K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];

type DataPropertiesOnly<T> = {
  [P in DataPropertyNames<T>]: T[P] extends object ? DTO<T[P]> : T[P]
};

export type DTO<T> = DataPropertiesOnly<T>;
Run Code Online (Sandbox Code Playgroud)

我使用缩写词DTO来表示数据传输对象。感谢 l00ser2410656 提供的这个 Playground 演示