TypeScript - 通用约束可以提供“允许”类型? [英] TypeScript - can a generic constraint provide "allowed" types?
问题描述
type可转换< TKey,TValue> = {[index:TKey]:TValue}
这会产生以下错误:
索引签名参数类型必须是'string'或'number'。
有没有办法将 TKey
限制为'string'或'number'?
正如 @ TitianCernicova-Dragomir 所示,您无法使用 TKey
作为索引签名中的类型,即使它是相当于字符串
或数字
。
如果您知道 TKey
正好是 string
或 number
,您可以直接使用它,而不是在您的类型中指定 TKey
:
type StringIndexable< TValue> = {[index:string]:TValue}
type NumberIndexable< TValue> = {[index:number]:TValue}
Aside :事实证明,在TypeScript中的一堆地方,属性的索引类型必须是 string
,而不是号
。在这些地方, number
通常被视为 string
的一种子类型。这是因为在JavaScript中,当您使用它们时,索引会转换为 string
,导致这种行为:
const a = {0:hello};
console.log(a [0]); //输出hello
console.log(a ['0'])// * still *输出hello
因为你不能在后面使用 number
,所以我会忽略它;如果您需要使用数字键,TypeScript可能会让您,或者您可以手动转换为字符串
。回到答案的其余部分:
如果你想允许 TKey
比字符串
更具体,这意味着只允许某些键,您可以使用映射类型:
type可转换< TKey extends string,TValue> = {[TKey中的K]:TValue}
你可以通过传递字符串来使用它或者
type NumNames ='zero '| 'one'| '二';
const nums:可索引< NumNames,number> = {零:0,1:1,2:2};
type NumNumerals ='0'| '1'| 2’ ;
常数:可索引< NumNumerals,number> = {0:0,1:1,2:2};
如果您不想将关键字限制为特定文字或文字联合,您可以仍然使用 string
作为 TKey
:
const anyNums:可索引< string,number> = {uno:1,zwei:2,trois:3};
其实这个定义可索引< TKey,TValue>
非常有用,它已经存在于 TypeScript标准库作为记录< K,T>
:
键入NumNames ='zero'| 'one'| '二';
const nums:记录< NumNames,number> = {零:0,1:1,2:2};
因此,我建议您使用记录< K,T>
用于这些目的,因为它是标准的,其他TypeScript开发人员阅读你的代码更可能熟悉它。
希望有所帮助;祝你好运!
Given the following code...
type Indexable<TKey, TValue> = { [index: TKey]: TValue }
This produces the following error:
An index signature parameter type must be 'string' or 'number'.
Is there a way to constrain TKey
to be 'string' or 'number'?
As @TitianCernicova-Dragomir indicates, you can't use TKey
as the type in an index signature, even if it is equivalent to string
or number
.
If you know that TKey
is exactly string
or number
, you can just use it directly and not specify TKey
in your type:
type StringIndexable<TValue> = { [index: string]: TValue }
type NumberIndexable<TValue> = { [index: number]: TValue }
Aside: It turns out that in a bunch of places in TypeScript, the index type for properties is required to be a string
, and not number
. In such places, number
is usually treated as a kind of subtype of string
. That's because in JavaScript, indices are converted to string
anyway when you use them, leading to this kind of behavior:
const a = { 0: "hello" };
console.log(a[0]); // outputs "hello"
console.log(a['0']) // *still* outputs "hello"
Since you can't use number
in what follows, I will ignore it; if you need to use numeric keys TypeScript will probably let you, or you can convert to string
manually. Back to the rest of the answer:
If you want to allow TKey
to be more specific than string
, meaning only certain keys are allowed, you can use mapped types:
type Indexable<TKey extends string, TValue> = { [K in TKey]: TValue }
You'd use it by passing in a string literal or union of string literals for TKey
:
type NumNames = 'zero' | 'one' | 'two';
const nums: Indexable<NumNames, number> = { zero: 0, one: 1, two: 2 };
type NumNumerals = '0' | '1' | '2';
const numerals: Indexable<NumNumerals, number> = {0: 0, 1: 1, 2: 2};
And if you don't want to limit the key to particular literals or unions of literals, you can still use string
as TKey
:
const anyNums: Indexable<string, number> = { uno: 1, zwei: 2, trois: 3 };
In fact, this definition for Indexable<TKey, TValue>
is so useful, it already exists in the TypeScript standard library as Record<K,T>
:
type NumNames = 'zero' | 'one' | 'two';
const nums: Record<NumNames, number> = { zero: 0, one: 1, two: 2 };
I therefore recommend you use Record<K,T>
for these purposes, since it is standard and other TypeScript developers who read your code are more likely to be familiar with it.
Hope that helps; good luck!
这篇关于TypeScript - 通用约束可以提供“允许”类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!