TypeScript中索引签名的通用返回类型

时间:2017-08-19 11:12:01

标签: typescript generics

这是问题

interface Prop<T> {
   value: T;
}

class Property<T> implements Prop<T> {
   value: T;
   constructor(value: T) {
      this.value = value;
   }
}

class Node {
   this.props: { [index: string]: Prop<T> } // how do you define T?
}

T无法在此级别定义为需要,因为预期用途将与

一致。
const strProp = node.props<string>['strProp'];
const numProp = node.props<number>['numProp'];

换句话说,Node可以附加各种属性类型。

docs中似乎没有关于此事的任何内容(或者我只是没有看到它)。基本上我在这里真正需要的是通用索引器,例如:

this.props: <T>{ [index: string]: Prop<T> }

它存在吗?

免责声明 - 我不是在寻找解决方法,我知道有办法解决这个问题,但我想知道支持是否存在(我无法看到任何支持)关于回购的提案或未决问题)。有一些类似的问题,但没有具体的特定情况。

1 个答案:

答案 0 :(得分:1)

不,在TypeScript中,只有函数(包括方法)和类型(类,接口,类型别名)可以是通用的。

此外,它看起来并不像你要求的实际上有多大意义。要了解原因,让我们看一下您不一定感兴趣的解决方法之一:

abstract class Node {
  abstract propsGetter<T>(index: string): Prop<T>;
}

这里我们定义一个getter方法,它接受类型参数Tstring参数,并返回类型Prop<T>的值。这或多或少等同于索引属性。请注意,此方法的调用者,而不是实现者指定了类型Tindex

我想,你会这样称呼它:

declare const node: Node;
const strProp = node.propsGetter<string>('strProp');
const numProp = node.propsGetter<number>('numProp');

但是等等,没有什么可以阻止你这样称呼它:

const whatProp = node.propsGetter<string>('numProp'); // no error

如果您希望编译器以某种方式知道'numProp'参数将返回Prop<number>并且会出现错误,编译器会让您失望。 propsGetter的签名承诺,无论Prop<T>参数是什么,它都会为调用者想要的T值返回index

除非你为编译器描述index的类型(可能是一些字符串文字的集合)和T的类型之间的某种关系,否则这里没有类型安全性。 type参数对你没有任何帮助。您也可以删除type参数,然后执行以下操作:

abstract class Node {
  abstract propsGetter(index: string): Prop<{}>;
}

返回Prop<{}>值,您必须键入check或assert:

const strProp = node.propsGetter('strProp') as Prop<string>; // okay
const numProp = node.propsGetter('numProp') as Prop<number>; // okay

这与上面的非类型安全一样,但至少它是明确的。

const whatProp = node.propsGetter('numProp') as Prop<string>; // still no error but it's your responsibility

然后,由于我们不需要泛型参数,您确实可以使用索引器:

class Node {
   props: { [index: string]: Prop<{}> } 
}

回想一下,

  

除非你为编译器描述index的类型(可能是一些字符串文字的集合)和T的类型之间的某种关系,否则这里没有类型安全性。

您是否有某种方式告诉编译器哪些属性键应返回哪些属性类型?如果是这样,看起来你实际上并不想要一个纯string - 索引类型,而是一个标准对象:

abstract class Node {
  props: {
    strProp: Prop<string>,
    numProp: Prop<number>,
    // ... others ...
    [otherKeys: string]: Prop<{}> // default
  }
}

也许其中一个符合您的使用案例......并非您关心,因为您的免责声明不承认。如果您不在乎,请在我的第一句话之后忽略所有内容。

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