从类创建派生类型,但省略构造函数(打字稿)

Posted

技术标签:

【中文标题】从类创建派生类型,但省略构造函数(打字稿)【英文标题】:Create a derived type from class, but omit the constructor (typescript) 【发布时间】:2020-02-22 01:08:49 【问题描述】:

我有一个这样定义的接口和类:

interface Foo 
  constructor: typeof Foo;


class Foo 
  static bar = 'bar';

  constructor(data: Partial<Foo>) 
    Object.assign(this, data);
  

  someMethod() 
    return this.constructor.bar;
  

  prop1: string;
  prop2: number;

接口是必需的,以便this.constructor 是强类型的。但是,它破坏了我将普通对象传递给类构造函数的能力:

const foo = new Foo( prop1: 'asdf', prop2: 1234 );

// Argument of type ' prop1: string; prop2: number; ' is not assignable to parameter of type 'Partial<Foo>'.
//  Types of property 'constructor' are incompatible.
//    Type 'Function' is not assignable to type 'typeof Foo'.
//      Type 'Function' provides no match for the signature 'new (data: Partial<Foo>): Foo'.

我了解错误消息,但我不知道如何解决它。有什么办法有一个Partial&lt;Foo&gt; 可以让我传递一个普通的对象?这是一个游乐场:

Playground

【问题讨论】:

不确定你的意图是什么,好像你试图从实例访问静态属性,这是不可能的,接口也是多余的,checkout this 谢谢埃里克。您可以通过this.constructor 从实例访问静态属性,这样做并不少见。冗余接口也是必需的,因为您不能在类定义中键入 constructor 方法。这使用了“接口合并”,这是 TypeScript 的一个特性,也很常见:github.com/microsoft/TypeScript/issues/… 【参考方案1】:

这是从省略构造函数(如问题标题中所示)并保留常规方法的类创建派生类型的实际类型:

type NonConstructorKeys<T> = ([P in keyof T]: T[P] extends new () => any ? never : P )[keyof T];
type NonConstructor<T> = Pick<T, NonConstructorKeys<T>>;

与问题中的Foo 一起使用:

type FooNonConstructorKeys = NonConstructorKeys<Foo>; // "prop1" | "prop2" | "someMethod"
type FooNonConstructor = NonConstructor<Foo>;

【讨论】:

【参考方案2】:

我最终在这个精彩的答案中找到了我需要的东西:

how to remove properties via mapped type in TypeScript

该答案中的代码创建了一个包含 only 方法的派生类型。我需要做相反的事情。以下NonMethods&lt;T&gt; 帮助器创建了一个已删除所有方法的派生类型。

type NonMethodKeys<T> = ([P in keyof T]: T[P] extends Function ? never : P )[keyof T];  
type NonMethods<T> = Pick<T, NonMethodKeys<T>>; 

Here's the Playground

【讨论】:

【参考方案3】:

看起来你想定义一个接口然后使用它,那么你必须在接口本身而不是类中定义属性。

interface Foo 
  prop1: string; // define your properties here
  prop2: number;


class Foo 
  static bar = 'bar';

  constructor(data: Partial<Foo>) 
    Object.assign(this, data);
  

  someMethod() 
    return Foo.bar; // notice how I access static variables now
  



const foo = new Foo( prop1: 'asdf', prop2: 1234 );

Playground

【讨论】:

谢谢。我需要this.constructor,因为这是一个由其他类扩展的基类(例如抽象)。每个扩展类都会定义自己的“bar”值。

以上是关于从类创建派生类型,但省略构造函数(打字稿)的主要内容,如果未能解决你的问题,请参考以下文章

打字稿用函数创建自己的类型

打字稿接口和承诺返回一个对象/构造函数?

使用打字稿在构造函数中动态设置类属性

反应打字稿测试TypeError:MutationObserver不是构造函数

打字稿中的多个构造函数

类装饰器上的打字稿文档-返回“类扩展构造函数”的函数