我正在用TypeScript编写一个库,我想检查我的类型定义是否正确。通常,我想检查变量是否具有某种静态类型。我通常这样做:
let expectedToBeString : string = Api.callFunction("param1", 2, []);
但有时候,在我不知情的情况下,类型可能会扩展到any
,因此上面的表达式仍会编译。所以我想通过编写一个故意失败类型检查的表达式来确保不 any
。
有时我也想检查我的重载集是否适用于合法类型,但不适用于非法类型,但确保这一点的唯一方法是引发编译错误。
如何验证是否应该引发编译错误?
答案 0 :(得分:1)
有趣的问题。当TypeScript v2.8中发布conditional types时,假设在本月某个时间(2018年3月)出现,或者现在在typescript@next
出现,您将可以执行以下操作:
type ReplaceAny<T, R> = 0 extends (1 & T) ? R : T
ReplaceAny<T, R>
类型将为T
,除非 T
为any
,在这种情况下,它将为R
。正常类型T
不应满足0 extends (1 & T)
,因为1 & T
应至少与1
一样窄,0
不是1
的子类型}。但TypeScript中的any
类型违反了规则:它被认为是所有其他类型(或多或少)的超类型和子类型。这表示1 & any
变为any
,0 extends any
为真。因此,0 extends (1 & T)
的行为类似于any
探测器。
现在我们可以制作这样的便利功能:
const replaceAny = <R>() => <T>(x: T): ReplaceAny<T,R> => x as any;
如果您调用replaceAny<{}>()
,它会生成一个函数,该函数将接受任何输入,如果该输入的类型为{}
,则返回any
类型的值。
因此,让我们研究一些场景:
declare const Api: {
callFunctionS(...args: any[]): string,
callFunctionN(...args: any[]): number,
callFunctionA(...args: any[]): any,
}
let expectedToBeString: string;
expectedToBeString =
replaceAny<{}>()(Api.callFunctionS("param1", 2, []));
// okay
expectedToBeString =
replaceAny<{}>()(Api.callFunctionN("param1", 2, []));
// error, number not assignable to string
expectedToBeString =
replaceAny<{}>()(Api.callFunctionA("param1", 2, []));
// error, {} not assignable to string
前两个表现符合您的预期,其中expectedToBeString
对callFunctionS()
感到满意,但对callFunctionN()
感到愤怒。新的行为是它对callFunctionA()
感到愤怒,因为replaceAny<{}>()
导致返回值为{}
而不是any
,而{}
是不能转让给string
。
希望有所帮助;祝你好运!