优势
- ts的静态类型使得我们在开发过程中,发现潜在问题;
- 编辑器可以给出更好的代码提示;
- 代码语义更加清晰易懂,类型声明可以直观的看到代码中潜在语义,这样写出的代码可读性会更高一些;
// type Point = {x: number, y: number} // 这是一种类型别名的语法interface Point {x: number, y:number}function tsDemo(data: Point) {return Math.sqrt(data.x ** 2 + data.y ** 2)}tsDemo({x: 1, y: 2});
编辑器配置
vscode 设置,
- tab size 设置为
2 - Quote Style 设置为
single - 为了格式化文档,我们安装插件:
Prettier - Code formatter - 勾选 Editor: Format On Save
npm install -g typescript
此时运行 node demo.ts 是不行的,浏览器或者node环境中是不能运行ts的。
我们需要先 tsc demo.ts 把代码编译成 demo.js,
然后执行 node demo.js
为了解决这个问题,我们安装 ts-node , 然后执行 ts-node demo.ts
npm install -g ts-node// 如果执行 ts-node demo.ts 报错 console.log(...) 可以安装下面的依赖:npm install -D tslib @types/node
静态类型深度理解
const count: number = 2021;
count 为number类型后,count 这个变量会具备 number 类型所有的属性和方法
// 自定义变量interface Point {x: number,y: number}const point: Point = {} // 这样定义一个Point类型是会报错的,我们可以写成后面的形式:const point: Point = { // 这样写就不会报错了x: 3,y: 4}
理解
- Point 类型是一个自定义的静态类型
- point 变量上具备Point静态类型上的属性和方法
定义静态类型后不仅意味着数据类型不能修改,而且对应变量上的方法和属性基本也就确定了,正是因为这样,编辑器在使用静态类型的时候,才能给我们很好的提示。 这就是我们所说的 type 的深度理解。
基础类型和对象类型
静态类型可以帮助我们更直观的判断变量的内容是什么,比如 let count: number 我们就可以知道 count 的内容一定是数字,否则就不对了。
// 基础类型 null, undefined, symbol, boolean, void...const count: number = 123;const job: string = 'web开发';//对象类型: 对象、数组、类、函数类型等const person: {name: string,age: number} = {name: 'cos',age: 18}const arr: number[] = [1, 2, 3];class Phone {}const iphone: Phone = new Phone();// getTotal 是一个函数类型,函数执行的返回值是一个数字类型const getTotal: () => number = () => {return 123;}
类型注解和类型推断
type annotation 类型注解,我们来告诉TS变量是什么类型
type inference 类型推断,TS会自动的尝试分析变量的类型
如果ts能够自动分析变量类型,我们就什么也不需要做了
如果ts无法分析变量类型的话,我们就需要使用类型注解
// 这些ts是可以推断类型的,我们就不用使用类型注解了const num1 = 1;const num2 = 2;const total = num1 + num2;const obj = {name: 'cos',age: 28}// 这里的x,y 是无法推断类型的,所以就要使用类型注解function getTotal(x: number, y: number) {return x + y;}getTotal(1, 2);
函数相关类型
ts中定义函数的方式和JS中定义函数的方式是一致的
function func() {}const func = function() {}const func = () => {}
// 一般来说类型推断可以帮我们确定数据类型,但是像这种函数返回值的类型一般我们是需要写类型注解的,// 因为有时候可能会在函数内部错误书写导致数据类型发生变化,所以我们一般是要声明函数返回值数据类型的function add(first: number, second: number): number {return first + second;}const total = add(1, 2);
// void 表示函数不应该有返回值function func(): void {console.log('func'); // 这样写时不会报错的return 'func'; // 如果这样写就会报错}
// never 表示函数永远不可能执行到最后function errorEmitter(): never {throw new Error();console.log('never');}// 还有哪些函数式永远知行不到最后的呢:while(true) {}// ... 这里的函数是执行不完的
// 函数解构function add({first, second}: {first: number, second: number}): number {return first + second;}const total = add({first: 1, second: 2});// 注意:只要是解构都必须 按照上述的语法写,即便是只有一个参数function add({first}: {first: number}): number {return first;}
复习
// 基础类型 boolean number string void undefined symbol nulllet count: number;count = 123;//注:如果分成两行来写,则需要类型注解
// 对象类型: {} , class, function, []// 如果我们希望函数的参数和返回值都有固定的数据类型,有2种方式可以约束参数和返回值// 例:字符串 转 数字const func = (str: string): number => { // 这里其实不写number 类型推断也能推断出返回值为numberreturn parseInt(str, 10);}// 所以我们可以写成这样:const func = (str: string) => {return parseInt(str, 10);}// 但是这种写法是不能省略 number 的,否则语法就不正确了const func1: (str: string) => number = (str) => {return parseInt(str, 10);}/*: 后面跟的一般是类型= 后面跟的是具体实现函数的入参一般是需要类型注解的但是返回往往可以通过类型推断推断出结果*/const date:Date = new Date();// 这里其实不需要写Date类型,因为ts可以推断出类型为Dateconst date = new Date();// 其他的caseinterface Person {name: string}const rawData = '{"name": "cos"}';const newData: Person = JSON.parse(rawData); // 这种JSON方法处理的数据是无法通过类型推断得出结论的,所以我们需要类型注解// 如果 一个变量可能是数字类型 也可能是 字符串类型let temp: number | string = 123; // 这里不能用 const? 为什么?temp = '456'
数组
const numberArr: number[] = [1, 2, 3]; // 是一个数组,并且每一项都是数字// 如果数组中既有number 又有 string, 应该如何写类型注解:const arr: (number | string)[] = [1, '2', 3]; // 这就表示这个数组既有数字又有字符串const stringArr: string[] = ['a', 'b', 'c'];const undefinedArr: undefined[] = [undefined]; // 这个数组就只能有undefined,否则就回报错
// 数组中也可以存储复杂的数据类型
const objArr: {name: string, age: number}[] = [{name: 'cos', age: 18}]// 这种写法读起来比较复杂,不容易理解
我们可以使用类型别名:type alias:类型别名。
type User = {name: string, age: number }const objectArr: User[] = [{name: 'cos',age: 18}]
注意:
class Teacher {name: string,age: nuber}const objectArr: Teacher[] = [new Teacher(),{name: 'cos',age: 28}]// 这里虽然我们写了类型危 Teacher ,// 但是 不通过 new Teacher() 这种形式也是可以的,只要是传递一个对象,里面结构和Teacher保持一致即可
元组 tuple
当一个数组长度固定,且没个元素的类型固定的时候,就可以把该数组称为一个元组了。
比如,有一个数组,第一项为字符串,第二项为字符串,第三项为数字,
const info = ['cos', 'male', 18];// 这种我们写成数组的话:const info: (string | number)[] = ['cos', 'male', 18];// 这种写法中,我数组中的3个值只要是string或者number类型就可以,就约束不住了,// 这个时候我们可以考虑使用元组:const info: [string, string, number] = ['cos', 'male', 18];// 这个时候我们就可以把这3个元素唯一约束了。
比如 excel中导出的 .csv所产生的数据结构,在转化成js的时候,用元组去管理是一个比较好的方式。
const arr: [string, string, number][] = [['cos', 'meal', 18],['rose', 'meal', 28],['jack', 'femeal', 8],];
