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

时间:2020-04-17 16:42:30

标签: typescript typeguards

这是一个基于更复杂的旧代码的精炼示例。假设您具有这样的功能:

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); 

2 个答案:

答案 0 :(得分:1)

Function overloads将执行此操作。例如,

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

请参见Typescript Playground

答案 1 :(得分:0)

如果您有一个void返回函数,其作用是缩小其参数之一的类型,并且如果您运行的是TypeScript 3.7或更高版本,则可以将其设为{{3} },编译器将考虑该断言。断言函数的返回类型以asserts修饰符开头,后跟我们希望函数断言的条件。此条件可以是函数输入之一的名称,也可以是表示函数输入is的类型比其声明的类型窄的assertion function。这是我们如何使用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返回函数上起作用,因此您不能拥有同时充当类型断言并返回某些值的函数。还有其他警告(例如type predicate)。但是您的问题非常适合断言函数,以至于如果我不了解,我想这是语言设计者之一提出的,目的是展示断言函数的功能! ?

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

require explicit annotations to be called