简体   繁体   English

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

[英]Generic return type for index signature in TypeScript

Here's the problem 这是问题所在

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 can't be defined at class level here as needs as the intended use would be along the lines of T不能在此根据需要在类级别进行定义,因为预期用途将遵循

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

In other words, a Node can have various property types attached to it. 换句话说, Node可以具有附加的各种属性类型。

There doesn't appear to be anything in the docs about this (or perhaps I'm just not seeing it). 文档中似乎没有关于此的任何内容(或者也许我只是没有看到它)。 Basically what I'm really looking for here is a generic indexer, for example: 基本上,我真正要寻找的是通用索引器,例如:

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

Does it exist? 是否存在?

Disclaimer - I'm not looking for workarounds, I understand there are ways around this but I'd like to know whether or not the support is there (I couldn't see any proposals or outstanding issues on the repo for this). 免责声明-我不是在寻找解决方法,我知道有解决办法,但我想知道是否有支持(为此,我在回购中看不到任何建议或未解决的问题)。 There were some similar issues but nothing specific to this particular scenario. 存在一些类似的问题,但是没有特定于此特定方案的问题。

No, in TypeScript only functions (including methods) and types (classes, interfaces, type aliases) can be generic. 不,在TypeScript中,只有函数(包括方法)和类型(类,接口,类型别名)可以是通用的。


Additionally, it doesn't look like what you're asking for actually makes much sense. 此外,您所要求的看起来似乎没有任何实际意义。 To see why, let's look at one of those workarounds you're not necessarily interested in: 要了解原因,请看一下您不一定感兴趣的一种变通方法:

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

Here we define a getter method which takes a type parameter T and a string parameter and returns a value of type Prop<T> . 在这里,我们定义了一个getter方法,该方法采用类型参数Tstring参数,并返回Prop<T>类型的值。 This is more or less the equivalent of an indexed property. 这或多或少等同于索引属性。 Notice that it is the caller , not the implementer of this method that specifies both the type T and index . 请注意,同时指定类型Tindex是此方法的实现 ,而不是该方法的实现

You would, I suppose, call it like this: 我想您应该这样称呼它:

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

But wait, nothing stops you from calling it like this: 但是,等等,没有什么可以阻止您这样调用它:

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

If you were expecting that the compiler would somehow know that the 'numProp' parameter would return a Prop<number> and that there would be an error, the compiler would disappoint you. 如果您期望编译器以某种方式知道'numProp'参数将返回Prop<number>并且会出现错误,则编译器会让您失望。 The signature of propsGetter promises that it will return a Prop<T> for whatever value of T the caller wants, no matter what the index parameter is. propsGetter的签名承诺,无论index参数是什么,无论调用者想要什么T值,它都将返回Prop<T>

Unless you describe for the compiler some relationship between the type of index (presumably some collection of string literals) and the type of T , there's no type safety here. 除非您为编译器描述index的类型(可能是字符串文字的某种集合)和T的类型之间的某种关系,否则这里没有类型安全性。 The type parameter does nothing for you. type参数对您没有任何帮助。 You might as well remove the type parameter and just do something like: 您也可以删除type参数,然后执行以下操作:

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

which returns a Prop<{}> value you have to type check or assert: 它返回一个Prop<{}>值,您必须键入check或assert:

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

This is just as non-type-safe as the above but at least it is explicit about it. 就像上面的非类型安全一样,但至少对此是明确的。

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

And then since we don't need the generic parameter you can indeed use an indexer: 然后,由于我们不需要通用参数,因此您确实可以使用索引器:

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

Recall, 召回,

Unless you describe for the compiler some relationship between the type of index (presumably some collection of string literals) and the type of T , there's no type safety here. 除非您为编译器描述index的类型(可能是字符串文字的某种集合)和T的类型之间的某种关系,否则这里没有类型安全性。

Do you have some kind of way to tell the compiler which property keys should return which property types? 您是否可以通过某种方式告诉编译器哪些属性键应返回哪些属性类型? If so, this is looking like you don't actually want a pure string -indexed type but a standard object of the sort: 如果是这样,这看起来像您实际上并不需要纯string索引类型,而是这种标准对象:

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

Maybe one of those meets your use case... not that you care, as your disclaimer disclaims. 也许其中之一符合您的用例...正如您的免责声明所指,您不在乎。 In the case that you don't care, please ignore everything after my first sentence. 如果您不在乎,请忽略我第一句话之后的所有内容。

Hope that helps. 希望能有所帮助。 Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM