Day05:【TypeScript 学起来】TS 指定型别的三种方法

Q: 为什麽一个男业务(30岁)会约我一个工程师(24岁)去园区的星巴克?
A: 根据哥多年的经验,他应该是有个超屌的idea只差工程师去实现了

原来工程师除了应付pm 也要学会怎麽应付业务 XDDD
今天先来学怎麽应付 TypeScript 最需要的型别指定比较实际 GO


在 TypeScript 中, 有三种方法可以去指定型别。包含:Type Inference (型别推断) 、 Type Annotation(型别注解) 、Type Assertions(型别断言)。


Type Inference (型别推断)

如果没有明确指定型别, TypeScript 会依照型别推断(Type Inference)的规则推断出一个型别。如下,x 会型别推断为 number 型别。 当 x 再赋值字串型别时, 就会报错。

let x = 3;
x = "hello"// error: Type 'number' is not assignable to type 'string'.


Type Annotation (型别注记)

TypeScript 除了可以自动型别推断外, 我们可以手动指定型别,让我们之後使用变数赋值的时候,可以方便debug。

在变数後使用即可。 入下面例子, age变数被指定爲 number 型别, 之後赋值字串型别 "32"时, 则会报错。

let age: number = 18; // number variable
let person: string = "iris"; // string variable
let isUpdated: boolean = true; // boolean variable

age = "32";//error: Type 'string' is not assignable to type 'number'.
isUpdated = false; //ok

console.log(age); //18
console.log(person); //iris
console.log(isUpdated); //false

Type Assertions(型别断言)

有时候你比 TypeScript 更知道你要的资料型别,TypeScript 是允许你你覆盖它的推断的, 但我们要慎用。

以下例子,变数 obj 被 TypeScript 推断为 {},没有属性,所以是无法添加 age 或 name 属性的。

let obj = {};
obj.age = 18; //error: property 'age' does not exist on `{}`
obj.name = 'iris'; //error: property 'name' does not exist on `{}`

如果我们要新增属性,这时候可以使用 Assertions 断言来指定型别,有两种语法可以使用:

//使用介面(Interfaces)来定义物件的型别(後面会讲到)
interface Foo {
  age: number;
  name: string;
}

//语法1: 值 as 型别
const obj2 = {} as Foo;
obj2.age = 18;
obj2.name = "iris";

const obj3 = {
  age: 18,
  name: "iris"
} as Foo;

//语法2: <型别>值
const obj4 = <Foo>{
  age: 18,
  name: "iris"
};

console.log("assertions-as", obj2); //{ age: 18, name: 'iris' }
console.log("assertions-as", obj3); //{ age: 18, name: 'iris' }
console.log("assertions-<type>", obj4); //{ age: 18, name: 'iris' }

语法

值 as 型别
<型别>值

⚠ 这两种写法的效果是一样的,但在 tsx 语法(React 的 jsx 语法的 ts 版)中必须用後一种(as), 因为跟 jsx 的语法都会使用<div> <span> <Xxxx>等进行撰写,<型别>值 再拿来使用会降低可读性或造成误会。

Assertions 要慎用

  1. 如果没有按照约定增加属性, TS 不会报错提醒。
interface Foo {
  age: number;
  name: string;
}

const foo = {} as Foo;

// ahhh, 忘记了什麽? 没加属性,没报错提醒。 或是少一个属性也不会报错。
  1. 如果 interface 被重构, 容易导致断言也出错。
interface Foo {
  age: number;
  name: string;
}

const foo = <Foo>{
  // 编译器将会提供关於 Foo 属性的代码提示 
 // 但是开发人员也很容易忘记添加所有的属性 
// 同样,如果 Foo 被重构,这段代码也可能被破坏(例如,一个新的属性被添加)。
};
  1. 建议使用更好的方法
interface Foo2 {
  age: number;
  name: string;
}

const foo2: Foo2 = {
  // 编译器将会提供 Foo2 属性的代码提示, 少了 age 和 name 的属性 
};


下一篇终於要来笔记 TypeScript 资料型别那些事~期待一下,下篇见~

参考资料

https://basarat.gitbook.io/typescript/type-system/type-assertion
https://jkchao.github.io/typescript-book-chinese/typings/typeAssertion.html#%E7%B1%BB%E5%9E%8B%E6%96%AD%E8%A8%80%E8%A2%AB%E8%AE%A4%E4%B8%BA%E6%98%AF%E6%9C%89%E5%AE%B3%E7%9A%84


<<:  [重构倒数第11天] - 如何在 Vue 中写出高效能的网页渲染方式 ?

>>:  Ruby on Rails CRUD 之 D(Delete)

Day 9 - Rancher 丛集管理指南 - 架设 K8s(下)

本文将於赛後同步刊登於笔者部落格 有兴趣学习更多 Kubernetes/DevOps/Linux 相...

[重构倒数第27天] - 在 Vue 各种 CSS 的引入使用

前言 该系列是为了让看过Vue官方文件或学过Vue但是却不知道怎麽下手去重构现在有的网站而去规画的系...

冒险村25 - Design Pattern(5) - Service Object

25 - Design Pattern(5) - Service Object Service 相对...

量化交易30天 Day29 - 整理量化交易相关学习资源

量化交易30天 本系列文章是纪录一位量化交易新手的学习过程,除了基础的Python语法不说明,其他...

[Day 20] Node 注册事件 1

前言 昨天我们聊到, node 的 JS 层中的 IO method , 在作了相应的设定後, 就利...