如何提示 TypeScript 编译器两个泛型值必须相同?
Posted
技术标签:
【中文标题】如何提示 TypeScript 编译器两个泛型值必须相同?【英文标题】:How to hint to TypeScript compiler that two generic values must be the same? 【发布时间】:2019-12-10 10:57:37 【问题描述】:我有一个简化的函数,它接收一个字符串文字和一个返回 type: [mystringliteral]
的回调。
function myFunc<T>(type: T, callback: () => type: T ): ReturnType<typeof callback>
return type ;
除非我在调用时特别设置了T
,否则T
被推断为string
而不是文字,并且type
属性上没有类型强制。
// successfully raises compilation error
const x = myFunc<'abc'>('abc', () => ( type: 'def' ));
// does not raise an error
const y = myFunc('abc', () => ( type: 'def' ));
我正在为第三方 npm 包编写声明文件,所以我无法调用任何聪明的函数来提示编译器发生了什么。
我猜我要问的问题对于当前的 TypeScript 规范是完全不可能的(如果我们能做类似<T extends string literal>
这样的事情会很好),但我想我会问。
【问题讨论】:
【参考方案1】:这里有两个问题。第一个是让编译器推断字符串文字类型。为此,我们需要将string
的约束添加到T
。这将向编译器提示我们需要文字类型。
但这还不够。只需将T extends string
添加到签名中,编译器就会推断出'abc' | 'def'
的联合,并且仍然不会产生错误。为了解决这个问题,我们必须让编译器知道T
的第二次出现不应该用于推理。虽然有一个提议 here 为此添加语法,但它尚未实现。但是,我们可以使用 jcalz 建议的解决方法来获得所需的效果:
function myFunc<T extends string>(type: T, callback: () => type: NoInfer<T> ): ReturnType<typeof callback>
return type ;
type NoInfer<T> = [T][T extends any ? 0 : never];
// raises an error
const y = myFunc('abc', () => ( type: 'def' ));
【讨论】:
以上是关于如何提示 TypeScript 编译器两个泛型值必须相同?的主要内容,如果未能解决你的问题,请参考以下文章