使用这样的简单结构:
type Test<Source extends string[]> =
Source extends [infer Head, ...infer Tail] ? `${Head}${Head}` : never;
Typescript 抱怨 ${Head}${Head}
中的字符串插值说:Type `'Head'` is not assignable to type 'string | number | bigint | boolean'. Type 'Head' is not assignable to type 'number'.ts(2322)
...这对我来说没有多大意义,但我的搜索没有取得成果。 Source 必须是 string[]
所以 Head
,如果存在,必须是一个字符串,对吗?所以 ${Head}
必须完全有效。为什么 TS 抱怨无法将其分配给 number
?字符串也可以分配给 "string | number | bigint | boolean"
所以这个错误对我来说没有多大意义。我可以通过在 "Head extends string ? ... : ...
子句之间放置字符串插值来修复它,但我想知道为什么首先需要这样做。
答案 0 :(得分:1)
是和否。 看看下一个例子:
type Test0<Source extends string[]> =
Source extends [infer Head, ...infer Tail] ? Head : never;
type O = Test0<[never, 'a']> // no error, because that is how NEVER works
因为 string|never
返回 string
。
我认为在上述情况下检查 Head 是否为字符串要安全得多。
答案 1 :(得分:1)
错误的原因是 TypeScript 在推断类型之前不会考虑 extends string[]
约束。如果你看这种类型
type T<Head> = `${Head}`
您会看到相同的相当迟钝的错误消息(对模板文字的推断有点不稳定)。由于 T
不在这里推断 Head
,您当然可以只声明 type T<Head extends string> = ..
,但另一种选择是在额外的条件中对 Head extends string
约束进行编码:
type T<Head> = Head extends string ? `${Head}` : never
这就是为什么 Test
类型检查您是否添加了额外的、看似多余的条件:
type Test<Source extends string[]> =
Source extends [infer Head, ...infer Tail]
? Head extends string ? `${Head}${Head}` : never
: never;