1.TS基础类型和函数


TS笔记

计划三天看完TS课程,此为课程笔记

一点准备

npm i typescript -g 全局安装TS编译器
npm i ts-node -g 安装好后可在vscode右键run直接运行ts
tsc hello.ts可运行编译文件
tsc --init生成TS配置文件

配置tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "outDir": "./js"
  }
}

运行vscode检视任务
vscode -> 终端 -> 运行生成任务 -> tsc:监视

这样保存ts文件时 会自动编译出js文件,方便查看

数据类型

布尔 数字 字符串 数组

let married: boolean = false;   // boolean
let age: number = 25;           // number
let firstName: string = 'lzy'; // string

let arr2: number[]=[4,5,6];     // array
let arr3: Array<number>=[7,8,9];// array
let arr4: (string | number)[]=[7,8,9,'a'];// array

元组: 表示 类型 和 数量 固定的 数组
与数组的区别: 每一项可以是不同类型, 有预定义的长度,

const animal:[string,number,boolean] = ['lzy',25,true];  // tuple
let lzy:[string,number] = ['lzy',5]; // tuple
// 此处如果没定义类型,则在TS中下面两行会报错。因为类型
lzy[0].length; // OK
lzy[1].toFixed(2); // OK

枚举: 该数据类型的变量 只能为事先写好的几个类型

// 普通枚举
enum Color {
    Red,// 默认值为 0 
    Yellow,// 默认值为1
    Blue// 默认值为2
}
// 常量枚举
const enum Color2 {
    Red,// 默认值为 0 
    Yellow,// 默认值为1
    Blue// 默认值为2
}
// 常量枚举的变量名(如Red)会在编译时被完全删除,节省变量名开销,因为是常量,必然是固定值,调用这个固定值的地方会直接被替换为值

let myColors = [Colors.Red, Colors.Yellow, Colors.Blue];

symbol
表示唯一不变的类型

const sym1 = Symbol('key');
const sym2 = Symbol('key');
// 报错:此条件将始终返回false
console.log(sym1 === sym2)

使用Symbol 需要 ES6 编译辅助库

bigint
可以安全的 储存 和 操作 大整数

const max = Number.MAX_SAFE_INTEGER;// 2**53-1
console.log(max + 1 === max + 2); // true,因为溢出了

const max:bigint = BigInt(Number.MAX_SAFE_INTEGER);
console.log(max + 1 === max + 2); // 报错,BigInt 不能直接 + number类型
console.log(max + 1n === max + 2n); // 代表BigInt(1)

使用 BigInt 需要 ESNext 的编译辅助库
JS 原始数据类型 BigInt Number,ts 里的类型 bigint number

any
任意类型,可以被赋值任何类型数据的类型

null undefined
null 和 undefined 是其他类型的子类型,可以赋值给任意类型.
但,TS配置文件设置了strictNullChecks:true时,直接这样赋值会报错
null 和 undefined 可以相互赋值

void
表示没有任何类型,当函数没有返回值时,被认为是void类型

never
never 是其他类型的子类型,表示永远不会被执行到的值

function error(message: string): never {
    throw new Error(message);
}
function fn(x: number | string) {
  if (typeof x === 'number') {
    // x: number 类型
  } else if (typeof x === 'string') {
    // x: string 类型
  } else {
    // x: never 类型
    // --strictNullChecks 模式下,这里的代码将不会被执行,x 无法被观察
  }
}

never 和 void 的区别: void 可以是 null 或 undefined
拥有 never 返回值类型的函数无法正常返回,无法终止,或会抛出异常。

function validateCheck (v:never) {}
function test (stringOrNumber: string | number) {
    if(typeof stringOrNumber === 'string') {
        return 
    }
    // 报错number类型不能赋值给never
    validateCheck(stringOrNumber)
}

function validateCheck (v:never) {}
function test (stringOrNumber: string | number) {
    if(typeof stringOrNumber === 'string') {
        return 
    } if(typeof stringOrNumber === 'number') {
        return
    }
    // OK!
    validateCheck(stringOrNumber)
}

类型推导

指 编程语言中 能自动推导出 值 的类型的能力,一般强类型语言才有
定义未赋值时,会推论为any类型

let username2;
username2 = 25; // 自动推理为number类型
username2 = 'lzy';// string类型

包装对象

JS有两类数据类型, 原始数据类型(null undefined boolean number string Symbol) 和 对象类型
所有原始数据类型都没有 属性 或 方法 可供使用,仅仅是储存一个数据.

但字符串数据 却可以直接调用 splice等方法,
这是因为 当 调用 基本数据类型 的方法时, JS 会把 原始数据类型 强制性切换为 对象类型,
c# Java中都有这个概念,叫 自动装箱,

let isOK: boolean = true; // 编译通过
let isOK: boolean = Boolean(1) // 编译通过
let isOK: boolean = new Boolean(1); // 编译失败 期望的 isOK 是一个原始数据类型

联合类型

表示 取值可以时多种类型中的一种
未赋值时 联合类型 上只能访问 两个类型共有的 属性或方法

let name:string | number // 联合类型  
console.log(name!.toString()); // 公共方法
name = 10;
console.log(name!.toFixed(2)); // number方法
name = 'zf';
console.log(name!.toLowerCase()); // 字符串方法

类型断言

将联合类型的变量 指定为 更加具体的类型

let name: string | number;
console.log((name as string).length);
console.log((name as boolean).length); // 报错,不能指定为联合类型外的类型
console.log((name as any as boolean).length); // 双重断言,OK

字面量类型和类型字面量

字面量类型 一个字面量就是一个类型,类型和值必须一致.

const up:'Up' = 'Up' // 这样写也是字面量类型,只不过无法复用
type OneToFive = 1 | 2 | 3 | 4 | 5;
type Bool = true | false;

字面量类型本身并不是很实用,但是可以在一个联合类型中组合成一个强大的抽象

类型字面量 写法很像一个对象

type Person = {
  name:string,
  age:number
};

// 注意写法: 不要和enum的写法搞混
enum Color {
    Red,// 默认值为 0 
    Yellow,// 默认值为1
    Blue// 默认值为2
}

TS函数

函数的类型约束主要是 入参 和 返回值

函数的声明方式有两种,function关键字来声明 表达式声明

表达式声明时,如果把类型约束写在函数里,则变量类型是根据函数推导出来的类型。

// function关键字声明 定义类型
function hello(name:string):void {
    console.log('hello',name);
}

// 表达式声明 定义类型
type GetUsernameFunction = (x:string,y:string)=>string;
type GetUsernameFunction2 = {(x:string,y:string):string}
let getUsername:GetUsernameFunction = 
function(firstName,lastName){
  return firstName + lastName;
}
// 表达式声明时,如果把类型约束写在函数里,则变量类型是根据函数推导出来的类型。

支持 可选 默认值 剩余参数 函数重载 四种写法

注意print(name:string = 'lzy',age?:number) 可不传第二个参数,

age的类型改成age:number | undefined 还是必须传第二个参数,只不过可以为undefined

// 默认参数,可选参数 和 ES6一样
function print(name:string = 'lzy',age?:number):void {
    console.log(name,age);
}
// 剩余参数
const sum = (...args: string[]): string => {
    return args.reduce((memo, current) => memo += current, '')
}
sum('a', 'b', 'c', 'd')

Function关键字声明的函数才能重载(伪重载,只是对类型的重载)

重载使用场景,输入和输出存在某种关联,参数的个数不一致时实现的逻辑也不一致

注意: 函数的重载,无法用泛型替代。????????? 存疑???

// 函数重载
// TS中的函数重载,表现为 同一个函数提供多个函数类型定义
// Java中的重载,表现为 同名函数 参数不一样
function toArray(value: number): number[];
function toArray(value: string): string[];
function toArray(value: string | number): string[] | number[] {
  // 只有一个具体的实现
  // 此处返回值可不写 : string[] | number[] ,但入参必须能兼容上面两个重载。
  if (typeof value === "string") {
    return value.split("");
  } else {
    return value.toString().split("").map(Number);
  }
}
let arr1 = toArray(1);
let arr2 = toArray("2");

// 上面的重载和这里一样的效果,那这样看重载好像也没什么用?
function attr2(val: string|number): void {
    if (typeof val === 'string') {
        obj.name=val;
    } else {
        obj.age=val;
    }
}
// 重载解决了下面这种情况
// 要求两个参数,要不都是string,要不都是string[]
function attr3(a: string,b: string): void;
function attr3(a: string[],b: string[]): void;
function attr3(a: any,b: any): void {
}

typeof keyof 函数this类型约束

TS中:

typeof 取变量的类型

keyof 取的是类型的key的集合

this 可在函数的第一个参数处做类型约束

注意: 如果 type 关键字后面的 typeof 会被视为 TS语法,具有获取 实例类型的功能,
或 getName(this: typeof person, key: PersonKey) 冒号后的typeof,也能被识别为TS
返回的是 类型本身
而语句中的 typeof 会被视为 js语法, 非获取类型的功能,而是返回类型字符串

const person = { name: "lzy", age: 25 }
type Person = typeof person;
type PersonKey = keyof Person;

function getName(this: Person, key: PersonKey) {
  return this[key];
}
getName.call(person, "name");

let a = typeof person
// let a: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"

其它笔记

?. 是js语法,链运算判断符,这个值没有值就不继续取值了

! 是TS语法,非空断言,断言该值必不为空,无需进行null检测。

注意: ele?.style.color = "red" 编译器会报错,

因为 ele?. 真不存在时实际上是返回undefined,运行会报错。

类 也是一个 类型(就像symbol,number,boolean一样),

构造完一个类后得到两个类型,一个构造函数类型 一个实例类型.


文章作者: 罗紫宇
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 罗紫宇 !
  目录