打字稿中的运行时类型安全

萨钦·帕萨尔(Sachin Parashar)

我试图更好地理解Typescript中的类型安全性,并遇到了以下具有此功能的场景:

function test(x: number){
    console.log(typeof x);
}

如果我以这种方式调用此方法-test('1')它会引发编译时错误,但如果将其更改为此方法,它将运行良好:

let y: any = '1';
test(y);
//works fine
//Outputs "string"

据我了解,将“ x”声明为数字仅在编译时有效,而Typescript仅强制执行编译时类型安全而不是运行时。因此,我想知道我是否正确理解了这一点或遗漏了什么,还有什么是确保运行时类型安全的所有不同方法?

马西耶·西科拉(Maciej Sikora)

TypeScript是两种合并的语言:

  1. 类型级别语言
  2. 价值等级语言

第一个作为所有类型注释都可见,这是纯JavaScript中不存在的语法。每个类型注释和类似保留字type, interface, enum, as, in都是类型级别语言的一部分。TS在编译过程中首先要做的是检查语法和类型级别语言的语法以及值级别语言上注释的正确性。

第二种是值级语言,它是完全正确的JS语法。它还具有ECMAScript建议书第3阶段的大多数功能。

第一部分被完全删除(例外是Enum,它在运行时中具有表示形式),第二部分保留在运行时中。

回到安全问题,是的,TypeScript在编写代码期间确保安全。您定义合同,编写合同的转换,并且TS正在检查与合同注释有关的代码的正确性。它消除了很多错误,例如错别字或使用null / undefined objects的方法和属性,并且还在程序流程中提供了可见的数据定义。

但是,它不能保护运行时。所有类型注解仅是假设,如果我们定义API具有端点响应的结构,则TS将保证代码遵循该结构,但是如果在运行时结构不同,则程序自然会失败,因为合同不等于数据。

回到你的例子

function test(x: number){
    console.log(typeof x);
}

定义功能test为它接受一个函数number作为参数,你说的没有什么不同,那么number将被传递给函数。因此,上面的实现实际上是一个常量,就像typeof x总是会返回一样number,因为注解正是如此。

// below is equal to your implementation, as number has one specific type
// caution is equal for TS, not for the runtime!
function test() {
  return console.log('number')
}

如果函数在输入方面是多态的,则应按此注释输入。您可能不知道可以得到什么输入,然后可以实施结构检查。该名称的正确名称是类型警卫考虑下面的例子

function test(x: unknown) {
  if (typeof x === 'number') {
    return x * 2; // return number
  }
  if (typeof x === 'string') {
    return x + '- I am string'; // return number
  }

  if (typeof x === 'object') {
    return x; // return object;
  }

  return null; // for others return null
}

现在函数test已将输出推断为union string | number | object | null通过使用控制流和条件,TS能够了解函数返回的内容。

每次您的代码处理某种多态类型时,您都可以使用类型保护来准确指定要使用的类型。该检查由结构完成(因为在运行时中仅存在结构,因此在代码编写过程中类型仅注释结构),因此您可以检查typeofinstanceof或者对象是否具有特定的键或值。

要记住的非常重要的事情-类型是某些现有运行时结构的标签。标签/类型在运行时不存在,但结构确实存在。这就是为什么TS能够理解类型保护的原因,因为每种类型都引用某种结构。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章