TypeScript 5分钟上手开发 使用篇

121 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情 

什么是Ts

Typed JavaScript at Any Scale. 具有类型的JavaScript,适用于任何大小的项目。 我们可以理解为ts是用来hook js的,就是在js编译时判断类型,编译后和原本js代码完全相同

// hellow.ts

function test(name: string) {
    return 'Hello, ' + name;
}

console.log(sayHello('Tom'));

tsc hello.ts后实际代码和原本js完全相同

function test(name) {
    return 'Hello, ' + name;
}

console.log(sayHello('Tom'));

假如非string类型参数 sayHello(123)时候 上面代码直接报错, 下面代码则运行正常。

ts和js同属于弱类型语言(即会自动帮我们转化类型后计算,而不是开发者显示的写出转换代码) 所以ts会编译时校验类型,规避错误,js则不会,如遇到报错则会在运行时抛出, 其他非错误的异常显示情况则需要开发者自行检查判断。

优点

  1. 节省了很多判断异常的类型校验代码。
  2. 将错误信息从运行时提前到编译时抛出。

相同代码.ts会在编译时抛错,.js则是运行过后才抛错。所以ts将错误提前暴露

 let a = 1
a.split(' ')

为了规范,便于阅读通常 TypeScript 编写的文件以 .ts 为后缀, React项目pages页面,则以 .tsx 为后缀。

类型定义

基本类型

变量名称: 变量类型 内置8种类型

string number boolean undefined null object bigint symbol

let str: string = "jimmy";

注意 null 和 undefined 是所有类型的子类型

数组

type[] 来表示数组 类型type用来定义Shape(里面元素的类型)的, [] 也就是数组

let numberArray: number[] = [1,2,3,4,5]
numberArray.push('8'); // 报错,必须传push进去number的元素

ts同时也支持和java保持一致的泛型,这种更加通俗易懂

let numberArray: Array<number> = [1, 1, 2, 3, 5];

问题: 假如我想不同index不同类型的数组如何定义。

元祖

元祖可以定义数组中不同位置的类型。缺点是必须限定数组个数

// 相当于 let employee = [1, "Semlinker"]
let employee: [number, string] = [1, "Semlinker"];
// 结构也必须参数个数一致
let [id, username] = employee;
// let [id, username, age] = employee; // error


// 问号`?`表示参数可选
type Point = [number, number?, number?];
//以下三种方式定义Point类型变量都合法
// const x: Point = [10]; 
// const x: Point = [10,10]; 
const x: Point = [10,10,10]; 


// readonly 类型的同样后面不可改变数组的值了
const point: readonly [number, number] = [10, 20];

let x: [string, number];

对象类型,接口

java里面接口定义可以完全忽略,这里我们理解成为interface就是限定对象Shape形状(里面元素类型)的

interface Person {
    readonly id: number; 
    name: string; // 确定(类型)属性,name
    age: number;
    id?: number;  // 可选属性
    [propName: string]: any; // 任意属性

}

let tom: Person = {
    id: 123,
    name: 'Tom',
    age: 25
};

tom.id = 9527; // 会报错,因为定义的是只读属性


接口interface中定义的确定属性。 ----interface的定义 在定义接口属性的变量的时候 ---- let tom:Interface = {}

  1. 所有的确定属性都必须赋值
  2. 可选属性可以赋值也可以不赋值
  3. 如果有任意属性,则其他所有属性的类型都必须是任意属性中包含的

函数

// 函数声明
function funcName1(x, y) {
    
}
// 函数表达式
let funcName2 = function (x, y) {
    
}

分别定义如下

function funcName1(x:number, y:number): number {
    return  x + y
}

// rest为剩余参数数组,剩余参数的类型可以为任意类型
let funcName2: (x: number, y: number, ...rest: any[]) => number = function (x: number, y: number): number {
    return x + y;
};

如下定义,

  1. 可以给确定类型的参数赋值默认值。
  2. parameter?:type 定义可选参数parameter,类型为type,可选参数必须在末尾定义(确定类型参数后面定义)。
function funcName1(x:number, y:number = 1, z?:string): number {
    return  x + y
}

重载

同样是java的概念,即相同名称,不同参数类型,不同参数数量,就视为不同函数

例子: 数字和字符串翻转我们可以这样定义、 123 变 321 hellow 变 wolleh

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string | void {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

类型推论

在没有指定类型的时候ts会根据赋值情况推测出一个类型来。 触发类型推论的条件:声明的时候同时赋值了。

let name = 'jack' // 类型推论会认为name为string类型
name = 1001 // 所以会报错

any类型

可以为任意类型,即不校验类型

  1. 明确指定any类型
  2. 生命的时候不赋值 以上两点满足则为any类型
// 1.指定类型
let name: any = 'jack'
name = 10001

或者
// 2.声明不赋值
let name2
name2 = 'jack'
name2 = 10001

联合类型

即可以为多个类型中的任意一个类型 联合类型使用|分隔每个类型。

let name: string | number;

作为变量传递的时候,需手动判断是否可以用该类型api 赋值的时候,会根据类型指定,自动判断类型

赋值的时候类型确定的可以类型指定

let name: string | number;
name = 'jack'
console.log(name.length)

name = 7
console.log(name.length) // TS2339: Property 'length' does not exist on type 'number'.

作为变量的时候,不确定,需要自己判断

function getFullName(name: string | number) {
    // 如果那么传进来的是number就会报错
    // TS2339: Property 'length' does not exist on type 'number'.
    return name.length > 0 ? name : ''
}