这是一个基于更复杂的遗留代码的精简示例。假设你有这样一个函数:
function foo(val: string | number): void {
if (typeof(val) !== 'number') {
throw new Error('val must be a number');
}
// do something with number
}
是否可以编写foo
的签名,以便在调用它之后,编译器推断val
必须是一个数字?
const val: string | number = getVal();
foo(val);
// Compiler shouldn't complain here since a string would have cause foo to throw
const x = Math.sqrt(val);
函数重载将执行此操作。例如,
function foo(val: string): void;
function foo(val: number): number;
function foo(val: string|number) {
if (typeof(val) !== 'number') {
throw new Error('val must be a number');
}
return Math.sqrt(val);
}
Math.sqrt(foo(123)); // ok
Math.sqrt(foo('asdf')); // not ok
请参阅打字游戏场。
如果您有一个void
返回函数,它可以缩小其中一个参数的类型,并且如果您运行的是TypeScript 3.7或更高版本,则可以将其作为断言函数,编译器会考虑该断言。断言函数的返回类型以asserts
修饰符开头,后跟我们希望函数断言的条件。此条件可以是函数输入之一的名称,也可以是表示函数输入之一is
的类型比其声明的类型窄的类型谓词。以下是我们如何使用foo()
:
function foo(val: string | number): asserts val is number {
if (typeof (val) !== 'number') {
throw new Error('val must be a number');
}
// do something with number
}
因此,我们将void
更改为asserts val is number
。如果函数返回,val
的类型将根据需要从string | number
缩小到number
:
const val: string | number = Math.random() < 0.5 ? "str" : 123;
foo(val);
const x = Math.sqrt(val); // okay
请注意,断言函数仅适用于void
返回函数,因此不能同时作为类型断言的函数和返回一些值。还有其他注意事项(例如,它们需要调用显式注释(。但你的问题非常适合断言函数,如果我不更清楚的话,我想这是一位语言设计师为了展示断言函数的威力而提出的!😜
好吧,希望能有所帮助;祝你好运
游乐场链接到代码