TypeScript:是否可以根据函数调用是否成功来推断类型



这是一个基于更复杂的遗留代码的精简示例。假设你有这样一个函数:

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返回函数,因此不能同时作为类型断言的函数返回一些值。还有其他注意事项(例如,它们需要调用显式注释(。但你的问题非常适合断言函数,如果我不更清楚的话,我想这是一位语言设计师为了展示断言函数的威力而提出的!😜

好吧,希望能有所帮助;祝你好运

游乐场链接到代码

最新更新