打字稿中的运行时类型安全 [英] Runtime typesafety in typescript

查看:29
本文介绍了打字稿中的运行时类型安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was trying to better understand the type safety in Typescript and came across this scenario where I have this function:

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

如果我这样调用这个方法 - test('1') 它会抛出编译时错误,但如果我把它改成这样就可以了:

If I call this method this way - test('1') It throws compile time error but it works fine if I change it to this:

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

据我所知,将x"声明为数字仅在编译时有效,并且 Typescript 仅强制执行编译时类型安全而不是运行时.所以,我想知道我是否理解正确或遗漏了什么,还有哪些不同的方法可以确保运行时类型安全?

From what I understand is that declaring 'x' as number only works during compile time and that Typescript only enforces compile time typesafety not runtime. So, I wanted to know if I understand this correctly or missing anything and also, what all are the different ways to ensure runtime typesafety?

推荐答案

TypeScript 是两种合并的语言:

TypeScript is two merged languages:

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

第一个在所有类型注解中都是可见的,它是一种在纯 J​​avaScript 中不存在的语法.每个类型注释和保留字,如 type, interface, enum, as, in 都是类型级语言的一部分.TS 在编译时首先要做的是检查类型级语言的语法和句法的正确性,以及值级语言的注解的正确性.

The first is visible as all type annotations, it is a syntax which not exists in pure JavaScript. Every type annotation and reserved words like type, interface, enum, as, in are part of type level language. What TS is doing during compilation as first is checking correctness of grammar and syntax of type level language and correctness of annotations over value level language.

第二种是值级语言,完全正确的JS语法.它还具有 ECMAScript 提案第 3 阶段的大部分功能.

The second is value level language, it is fully correct JS syntax. It also has most of features from ECMAScript proposals stage 3.

第一部分被完全删除(Enum 除外,它在运行时中有表示),第二部分保留在运行时中.

The first part is fully removed (exception is Enum which has representation in the runtime), the second stays in the runtime.

回到关于安全的问题,是的,TypeScript 在编写代码的过程中确保安全.您定义合同,编写合同的转换,并且 TS 正在检查与合同注释相关的代码的正确性.它消除了一大堆错误,如拼写错误,或使用空/未定义对象的方法和属性,它还在程序流程中给出了数据的可见定义.

Back to the question about safety, yes TypeScript ensure safety during writing the code. You define the contract, write transformations of the contract, and TS is checking correctness of the code with relation to contract annotations. It removes a whole bunch of errors like typos, or using null/undefined objects methods and properties, it also gives visible definitions of the data during the program flow.

但是,它不保护运行时.所有的类型注解都只是假设,如果我们定义API具有端点响应的这样那样的结构,那么TS会保证代码会遵循这个结构,但是如果在运行时,结构会有所不同,程序自然会失败,因为合同不等于数据.

But, it does not secure the runtime. All type annotations are only assumptions, if we define API to have such and such structure of the end point response, then TS will guarantee that code will follow this structure, but if in the runtime, the structure will be different, the program will naturally fail, as contract not equals the data.

回到你的例子

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

将函数 test 定义为一个以 number 作为参数的函数,你说的没什么不同,然后 number 将被传递给函数.所以上面的实现实际上是一个常量,因为 typeof x 将始终返回 number,因为这正是注释所说的.

Defining function test as a function which takes number as an argument, you are saying nothing different then number will be passed to the function. So the above implementation is really a constant, as typeof x will always return number, because that exactly what annotations says.

// 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')
}

如果函数在输入方面是多态的,那么输入应该被这样注释.可能会发生您不知道可以获得什么输入的情况,然后您可以实施结构检查.正确的名称是 - type守卫.考虑下面的例子

If the function is polymorphic in terms of the input, then input should be annotated as such. It can happen that you don't know what input you can get, then you can implement checking of the structure. The proper name for that is - type guard. Consider below example

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 |数量 |对象 |空.通过使用控制流和条件,TS 能够理解函数返回的内容.

Now function test has inferenced output as union string | number | object | null. By using control flow and conditions, TS is able to understand what the function returns.

每次您的代码处理一些多态类型时,您都可以使用类型保护来准确指定您正在使用的类型.检查是由结构体来完成的(因为运行时只存在结构体,在写代码时type只对结构体进行注解),所以可以检查typeofinstanceof或者if object具有特定的键或值.

Every time your code deals with some polymorphic type, you can use type guards to specify exactly with what type you are working. The checking is done by the structure (because only structure exists in the runtime, type only annotates the structure during code writing), so you can check typeof, instanceof or if object has specific keys or values.

要记住的非常重要的一点 - Type 是一些现有运行时结构的标签.标签/类型在运行时不存在,但结构存在.这就是为什么 TS 能够理解类型保护的原因,因为每种类型都指代某种结构.

Very important thing to remember - Type is a label for some existing runtime structure. The label/type not exists during runtime, but structure does. That is why TS is able to understand type guards, as every type refers to some structure.

这篇关于打字稿中的运行时类型安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆