泛型扩展某些类的问题

时间:2019-02-15 17:15:04

标签: typescript

为什么在e4e5e6中出现错误?它们都匹配SomeClass类型,因此必须匹配通用RES

class SomeClass {
  a: string;
  b: number;
  c: boolean;
}

class ChildOfSomeClass extends SomeClass {}

const someFunc1 = <RES extends SomeClass>() => {
  const e1: SomeClass = { a: "aaa", b: 123, c: true }; // ok
  const e2: SomeClass = new SomeClass(); // ok
  const e3: SomeClass = new ChildOfSomeClass(); // ok

  // Type '{ a: string; b: number; c: true; }' is not assignable to type 'RES'.ts(2322)
  const e4: RES = { a: "aaa", b: 123, c: true };

  // Type 'SomeClass' is not assignable to type 'RES'.ts(2322)
  const e5: RES = new SomeClass();

  // Type 'ChildOfSomeClass' is not assignable to type 'RES'.ts(2322)
  const e6: RES = new ChildOfSomeClass();
};

我最终希望someFunc1返回RES | Promise<RES>,但是为了示例起见,我简化了它。

2 个答案:

答案 0 :(得分:2)

RES extends SomeClass表示类型RES描述的值集是类型SomeClass描述的值集的子集。想象以下情况:

class MyRES extends SomeClass {
   d: string;
}

这满足条件RES extends SomeClass,但是在您提供的所有构造方法中,都没有分配d

有很多方法可以解决此问题,“正确”的解决方案将取决于您要使用此方法完成的工作。例如,一种解决方案是使您的方法采用一些构造函数或转换器方法,以根据RES的已知现有属性创建一个SomeClass

const someFunc1 = <RES extends SomeClass>(toRes: (SomeClass) => RES) => {
  const e: RES = toRes({ a: "aaa", b: 123, c: true }); // ok
};

答案 1 :(得分:1)

这是因为RES 扩展了 SomeClass。想象一下:

class SomeClass {
  a: string;
  b: number;
  c: boolean;
}

class ChildOfSomeClass extends SomeClass {}

class OtherChild extends SomeClass { d: string }

并假设RESOtherChild(确实扩展了SomeClass),您的代码将如下所示:

const someFunc1 = () => {
  const e1: SomeClass = { a: "aaa", b: 123, c: true }; // ok
  const e2: SomeClass = new SomeClass(); // ok
  const e3: SomeClass = new ChildOfSomeClass(); // ok


  const e4: OtherChild = { a: "aaa", b: 123, c: true };  // Not OK, OtherChild needs d

  // Downcasting SomeClass to OtherChild is not ok
  const e5: OtherChild = new SomeClass(); 

  const e6: OtherChild = new ChildOfSomeClass(); //This is especially not OK
};

您可以通过仅使用SomeClass来解决此问题,然后可以传递任何子对象。