【问题标题】:TypeScript - How to represent an index signature as a generic typeTypeScript - 如何将索引签名表示为泛型类型
【发布时间】:2017-02-10 09:25:32
【问题描述】:

TypeScript 中的索引签名是这样定义的:

字典

[key: string]: T

数组

[index: number]: T

这些可以包装成一些简单的、可重用的类型:

type DictionaryIndex<T> = {
    [key: string]: T
}

type ArrayIndex<T> = {
    [index: number]: T
}

现在我想将它们包装成一个类型。我试过这个:

type Index<TKey extends string|number, TValue> = {
    [key: TKey]: TValue
}

由于以下错误,无法编译:

索引签名参数必须是“字符串”或“数字”类型。

这不可能吗?

到底是为了什么?

因为

foo(obj: Index<string, Bar>)
foo(obj: Index<string, Bar> & Fooable<string>)

看起来比

更整洁
foo(obj: { [key: string]: Bar })
foo(obj: { [key: string]: Bar, canFoo: (foo: string) => Bar })

【问题讨论】:

标签: generics typescript generic-constraints


【解决方案1】:

很酷的问题!
我认为原因是这对于尚未实现的编译器来说确实是一个边缘案例,可能是因为它不值得付出努力。

索引属性键只能是明显的数字,对象属性键只能是字符串或数字。所以最后你的约束只说明什么是事实,以及编译器需要通过特殊情况处理什么。
所以我再次假设圣安德斯放弃了这一努力;-)

但为什么不这样做

type StrIndex<TValue> = {
    [key: string]: TValue
}

type NumIndex<TValue> = {
    [key: number]: TValue
}

foo(obj: StrIndex<Bar>)
foo(obj: StrIndex<Bar> & Fooable<string>)

它不像您的解决方案那样简洁,但作为一种折衷方案,它似乎还可以,因为 XXXIndex 类型的集合限制为 2 个

【讨论】:

    【解决方案2】:

    另一种解决方案是使用Record 实用程序。

    foo(obj: Record<string, Bar>)
    

    https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-14
      • 1970-01-01
      • 2016-06-18
      • 2021-12-30
      相关资源
      最近更新 更多