1-ts常用知识点归纳

131 阅读7分钟

仅供自己学习,如有不对请大佬们斧正,谢谢

安装 typescript

npm i -g typescript

安装 ts-node

npm i -g ts-node

  • 就不用tsc 文件名.ts -> node 文件名.js

工程化环境下的TS编译

用 vite 创建一个ts环境

npm create vite@latest my-ts-demo -- --template vanilla-ts cd my-ts-demo npm i npm run dev

类型注解

  • 作用: 给一个变量注解一个类型 这个变量只能存放你注解的类型数据 限制了类型

常用基础类型的注解

  • 类型就是把类型小写就行了
let count: number;
count = 100;
// count = '100'//不能将类型“string”分配给类型“number”

let name: string = "ts";
name = "123";

let flag: boolean = true;
flag = false;

let id: symbol = Symbol('only');
id = Symbol('only-two');

let un: undefined = undefined;
let nu: null = null;

其它的类型注解

数组

  • 方式1: 类型[]
  • 方式2:Array<类型>
  • 规定数组中只能存放注解后的类型,保证数组中的类型是统一的
// => 只能存放string类型的数组
let userList: string[] = ["mm", 'rr', 'ly'];

let skillList: Array<string> = ["football", "sing song"];

元组

  • 可以让同一个数组中按指定规则存在元素,一个萝卜一个坑
    • 类型是可以多种的,也有类型限制的
    • 数组内部的个数不能多也不能少
    • 顺寻必须按照类型定义的顺序书写
let info: [number, string] = [1, "name"];

函数

  • 函数 参数 和 返回值的类型注解 [参数 + 返回值]
  • 一但进行类型注解之后,实参的传递必须按照类型注解要求的类型来传
  • 可以在函数执行之后,方便查看,返回的类型值
function add(a:number, b:number): number {
  return a + b
}
let sum = add(1, 2);// let sum: number ts的类型推断
console.log(sum);// 3

// 类型别名的方式
// 只适合函数表达式,可以同时指定 参数 + 返回值
type CustomFn = (a: number, b: number) => number
const plus:CustomFn = (n1, n2) => n1 + n2
console.log(plus(1, 2));//3

// 可选参数
// 所有必选参数必须放在可选参数的前面
function link(a: string, b: string, c?: string): string {
  if(c) {
    return a + b + c;
  }
  return a + b;
}
console.log(link('i ', 'love '))//i love 
console.log(link('i ', 'love ', 'you'))//i love you

// 没有返回值 void也是 TS中的一种类型
// 表示没有返回值意味着就不用变量去接收这个玩意了
function  forArr(arr: string[]): void {
  arr.forEach(item => console.log(item))
}
forArr(['1', '2']);

补充:

  • 枚举/never/any等类型看看官网

interface接口

  • 对一个对象的形状进行描述
    • 通常I字母打头,使用大驼峰
    • 可选属性 ?:
    • 扩展属性
interface IPerson {
  name: string,
  age: number,
  tall?: number,//可选参数
  readonly sex : string,//只读属性
  say: () => void,
  getSkill: (idx: number) => string
  [other: string]: any//额外补充
}
const person: IPerson = {
  name: 'ly',
  age: 18,
  sex: '女',
  some: 'football',
  say() {
    console.log('say some')
  },
  getSkill(idx) {
    switch (idx) {
      case 1:
        return '1';
      default:
        return '2'
    }
  }
}
// person.sex = ''//无法分配到 "sex" ,因为它是只读属性
console.log(person.age)

接口继承

  • 就是把继承的和自身的属性把必须要的属性都得有
interface Icar {
  color: string,
  price: number
}

interface IBMW extends Icar{
  tall: number,
  width: number
}

const bmw: IBMW = {
  tall: 130,
  width: 250,
  color: 'red',
  price: 500000
}
console.log(bmw);

总结:

  • 作用:描述对象的形状,约束对象的属性方法及类型

泛型

概念: 泛型可以在保证类型安全的前提下,让多个类型一起工作实现类型的复用

  • 函数传入一个参数原样返回 [参数类型和返回值类型一致]
function getId(value: string): string {
  return value;
}
getId('12');// 只能是string

// 问题这个函数不够通用了,比如我想支持 string/number/boolean/...
// 这种写法参数和返回值的类型都是 T,且T是不固定的,可以在调用的时候在确定T的类型
function getSome<T>(value: T): T {
  return value;
}
getSome<string>('1');
getSome(1);
getSome(false);

泛型和接口使用(常用api数据的定义)

  • 接口的嵌套
// => 基础的写法
interface IResult {
  name: string,
  age: number
}
interface IUser {
  code: number,
  message: string,
  result: IResult
}
const user: IUser = {
  code: 200,
  message: 'success',
  result: {
    name: 'jly',
    age: 18
  }
}

interface IUserList {
  code: number,
  message: string,
  result: IResult[]
}

const userLists: IUserList = {
  code: 200,
  message: 'success',
  result: [
    {
      name: 'jly',
      age: 18
    },
    {
      name: 'rr',
      age: 19
    }
  ]
}
console.log(user);
console.log(userLists);
  • 稍微进阶一点的写法(推荐:项目中还是比较常用的方式)
interface IResult {
  name: string,
  age: number
}
interface IApi<T> {
  code: number,
  message: string,
  result: T
}
const user1: IApi<IResult> = {
  code: 200,
  message: 'success',
  result: {
    name: 'jly',
    age: 18
  }
}

const userLists1: IApi<IResult[]> = {
  code: 200,
  message: 'success',
  result: [
    {
      name: 'jly',
      age: 18
    },
    {
      name: 'rr',
      age: 19
    }
  ]
}
console.log(user1);
console.log(userLists1);

泛型 和 类的配合使用

  • 创建一个通用的泛型队列
class Queque<T> {
  // data数组中只能存放 T类型的成员
  private data: T[];
  constructor() {
    this.data = [];
  }
  add(item: T) {
    this.data.push(item);
  }
  pop() {
    return this.data.shift();
  }
  size() {
    return this.data.length;
  }
  isEmpty() {
    return this.size() === 0;
  }
}
const strQueque = new Queque<string>();
const numQueque = new Queque<number>();

strQueque.add('1');
strQueque.add('2');
strQueque.add('3');
strQueque.isEmpty();
strQueque.size();
strQueque.pop();

numQueque.add(1);
numQueque.add(2);
numQueque.add(3);
numQueque.isEmpty();
numQueque.size();
numQueque.pop();

泛型总结:

  • 解决: 类型的复用
  • 泛型 + 函数
  • 泛型 + 接口
  • 泛型 + 类
  • 再去看看官网的高级玩法

TS高级类型

联合类型

  • 作用: 让一个变量同时支持多种类型的值
  • 语法 TypeA | TypeB
let someSth: string|number;
someSth = "this is name";
someSth = 100;
// someSth = true;//不能将类型“boolean”分配给类型“string | number”。

类型别名

  • 场景
    • 简化复杂类型的使用
    • 用来替代interface,做一些对象的shape描述
let value: string | number | boolean;
value = 'this is string'
value = 100
value = true

// => 别名后面再有这种类型的就可以直接复用了
type AType = string | number | boolean;
let valueA: AType;
valueA = 'this is string'
valueA = 100
valueA = true
// => 方式一
interface ISPerson {
  name: string,
  age: number
}
let p: ISPerson = {
  name: 'ly',
  age: 18
}

// => 方式二(开发中更常用)
type TypePerson = {
  name: string,
  age: number
}
let p2: TypePerson = {
  name: 'ly',
  age: 18
}

交叉类型

  • 作用: 多个类型合并成一个类型,被注解的变量需要同时满足多个类型的要求
  • 语法 TypeA & TypeB
    • 多用于interface接口
interface Size {
  width: number
}

interface Color {
  bgColor: string
}

let box: Size & Color = {
  width: 100,
  bgColor: 'red'
}
console.log(box);

字面量类型

  • 用处: 经常和我们的联合类型配合使用
    • 限制变量是某些中的一个,就比字符串类型更加精确
let str_some = 'this is str some';// let str_some: string
const str_any = 'this is str any';//const str_any: "this is str any"

type Direction = 'left' | 'right' | 'up' | 'down';
function changeDirection(d: Direction) {
  console.log(d);
}
changeDirection('left');
// => 限制变量是某些中的一个,就比字符串类型更加精确
// => 其实也可以使用枚举类型

TS泛型工具

  • 简化一些泛型操作
  • Partial
    • 作用: 构造一个新类型 将原有类型中的所有属性都设置为可选,进场和interface配合使用
interface IProps {
  name: string,
  age: number
}

// 自动全部变成可选属性
type PartialProps = Partial<IProps>
let user: PartialProps = {
  name: 'ly'
}
/*
鼠标移上去
type PartialProps = {
  name?: string | undefined;
  age?: number | undefined;
}
*/

Readonly

  • 构造一个新类型, 把所有的属性变成只读属性
interface IProps {
  name: string,
  age: number
}

// 自动全部变成只读属性
type ReadonlyProps = Readonly<IProps>
/*
鼠标移上去
type ReadonlyProps = {
  readonly name: string;
  readonly age: number;
}
*/

Pick

  • 作用: 构造一个新类型 从原有类型中挑选几个属性
    • 就是挑选属性的作用
  • 用法: 第一个参数 [接口的类型];第二个参数要的属性 [属性1 | 属性2 |...]
interface IProps {
  name: string,
  age: number,
  id: string
}

// 选则自己想要的属性
type PickProps = Pick<IProps, 'id' | 'name'>
/*
鼠标移上去
type PickProps = {
  name: string;
  id: string;
}
*/

Record

  • 作用: 构造一个对象类型 统一添加多个key 且他们是统一的
type RecordObj = Record<'name' | 'age', string>
let obj: RecordObj = {
  name: 'ly',
  age: '18'
}
/*
鼠标移上去
type RecordObj = {
  name: string;
  age: string;
}
*/

类型推论

  • 就是不写类型的时候,TS也会给你推导出变量的类型
  • 能写类型的地方就自己写,这个看着去吧

类型保护

1.联合类型的类型保护

interface Pig {
  eat: boolean,
  say: () => void
}

interface Dog {
  eat: boolean,
  run: () => void
}

function getAnimal(animal: Pig | Dog) {
  // 方式1 类型断言,我们来指定类型,TS不要去管了
  // ;(animal as Pig).say();
  // 方式2 通过in操作符
  if('say' in animal) {
    animal.say();
  }
}

函数的可选参数的类型保护

interface IGPerson {
  name: string,
  age: number
}

function getPersonInfo(baseName: string, person ?: IGPerson) {
  // 做一个判断确保person存在的时候采取读取 name属性
  if(person) {
    return baseName + person.name;
  } else {
    return baseName;
  }
}

TS编译规则文件 tsconfig.json

  • 去官网搜一下常用的配置项目
  • 一般不需要修改,除了一些定制化的需求

实在不会定义类型了就用any吧🐕