TypeScript 笔记——类型和接口

ts主要是为js添加类型系统,使问题在开发阶段暴露出来,有利于提早发现错误,避免使用时报错。另一方面,函数定义里面加入类型,具有提示作用,可以告诉开发者这个函数怎么用。
动态类型:当一个变量定义为number类型时后面还可从新赋值为string类型的,也就是说变量的类型是动态的
静态类型:引入ts后,变量的类型就可以被确定,在赋值错误的时候会有相关提示,可以更早的发现问题,解决问题。


一、类型

1、基本类型: number、string、null、undefined、boolean、undefined、object、symbol、bigint(target不低于es2020)

没有声明类型的变量被赋值为undefined或null时,类型会被推断为any(如果希望避免这种情况,则需要打开编译选项strictNullChecks),此时被赋值为undefined的变量的类型被推断为undefined,被赋值为null的变量的类型被推断为undefined

Object、object、{}的区别:
(1)、{}是Object类型的简写形式,所以使用Object时常常用空对象代替。
(2)、object筛选引用类型(即只有对象、数组、函数能定义为object类型)
(3)、Object除了undefined和null这两个值不能赋值给Object类型,其他任何值都可以赋值给Object类型。

//string类型
let str: String = 'wml'

//number类型
// number支持无穷大、各种进制、NaN
let num: number = NaN
let num1: number = Infinity

//boolean类型
let b: boolean = false

//object类型
let obj:object
obj:object = { a: '你好’};
obj = [1, 2];
obj = (a:number) => a + 2;

//null类型
let n: null = null

//undefined类型
let c: undefined = undefined

let v1: void = null //严格模式下void不能赋值为null
let v2: void = undefined
c = n //严格模式不能穿插赋值
n = c //严格模式不能穿插赋值
function myFn(): void {
  // return 123
}
console.log(b, str, "str", num, num1, v2, n, c, myFn());

2、any、unknown、never类型

any、unknown(ts称为顶层类型)区别:
1、any可以赋值给所有类型,unknown只能赋值给自己或者是any类型
2、unknown没法读任何属性 方法也不可以调用,而any类型可以
3、unknown比any更加安全
never类型(ts称为底层类型):该类型为空,不包含任何值。

function add(x:boolean|number) {
  if (typeof x === 'boolean') {
    // ...
  } else if (typeof x === 'number') {
    // ...
  } else {
    x; // never 类型
  }
}

3、联合类型

type:用来定义一个类型的别名。

// type A = void | number | never //联合类型时never会被忽略(即type A=void | number)
 type A = '常' | '挑' | '篮球'
 function Kun(value: A) {
   switch (value) {
     case "常":
       break
     case "挑":
       break
     case "篮球":
       break
     default:
       // 兜底逻辑
       const error: never = value
       break
   }
 }

4、交叉类型

interface People {
  name: string,
  age: number
}
interface Man {
  sex: number
}
const wu = (man: Man & People): void => {
  console.log(man);
}
wu({ name: '11', age: 123, sex: 1 })

5、值类型

let x: 'a' 
x='a' //正确
x='b' //报错
console.log(x)

6、包装对象类型与字面量类型

Boolean、String、Number、Symbol、BigInt五种包装对象之中,symbol 类型和 bigint 类型无法直接获取它们的包装对象(即Symbol()和BigInt()不能作为构造函数使用),但是剩下三种可以。

  • Boolean()
  • String()
  • Number()
'hello' // 字面量定义
new String('hello') // 包装对象定义

//包装对象即  String  同时包含字面量类型和包装对象类型
const s1:String = 'hello'; // 正确
const s2:String = new String('hello'); // 正确
//字面量类型即  string 只包含字面量类型
const s3:string = 'hello'; // 正确
const s4:string = new String('hello'); // 报错

使用类型时建议只使用小写类型,不使用大写类型。因为绝大部分使用原始类型的场合,都是使用字面量,不使用包装对象。而且,TypeScript 把很多内置方法的参数,定义成小写类型,使用大写类型会报错。

7、枚举类型(enum)

let obj = {
  red: 0,
  green: 1,
  blue: 2
}
console.log(obj);
enum Color {
  red = 1, //增长类型枚举
  green,
  blue
}
console.log(Color.red, Color.green, Color.blue);
字符串枚举
enum Color {
  red = 'red', //增长类型枚举
  green = 'green',
  blue = 'blue' //都要初始化
}
console.log(Color.red, Color.green, Color.blue);
enum Color {
  aa,
  yes = 2, //这里如果是数字的话定义bb不会报错,如果初始化时字符串就会报错
  bb,
  no = 'no'
}
console.log(Color.aa, Color.yes, Color.bb, Color.no);
interface A {
  red: Color.yes
}
let obj: A = {
  red: Color.yes
}
//const枚举(使用const会编译成为常量,而不是的话则会编译成对象)
enum Types {
  success,
  fail
}
let code: number = 0
if (code == Types.success) {
}

TypeScript 支持块级类型声明,即类型可以声明在代码块(用大括号表示)里面,并且只在当前代码块有效。

在这里插入代码片
if (true) {
  type T = number;
  let v:T = 5;
} else {
  type T = string;
  let v:T = 'hello';
}

二、接口

接口

1、interface遇到同名会合并类型
2、如果属性是可选的,就在属性名后面加一个?
3、如果属性是只读的,就加readonly(常用于函数,id)
4、对象的属性索引
一个接口中,最多只能定义一个字符串索引。字符串索引会约束该类型中所有名字为字符串的属性。
属性索引共有string、number和symbol三种类型。

下面例子中,我定义了[propName: string]为any类型,所以name,age,id,cb才不会报错,如果设置其他类型就会报错
5、接口继承
6、interface定义函数类型
7、字符串索引与数值索引
数值索引必须兼容字符串索引的类型声明。

interface B {
  xx: string
}
interface As extends B {
  readonly id?: number
  name: string
  age?: number
  [propName: string]: any //key为任意字符串类型,对象的属性索引
  readonly cb: () => boolean
}
//此处a的类型为接口B,所以必须符合B指定的结构,
let a: As = {
  name: '琳',
  // age: 88,
  d: 1,
  c: false,
  cb: () => {
    return false
  },
  xx: '66'
}
a.cb()
console.log(a);
interface Fn {
  (name: string): number[] //接收参数类型 返回类型
}
const fn: Fn = function (name: string) {
  console.log(name);
  return [1]
}
console.log(fn('c'));

//数值索引与字符串索引
interface A {
  [prop: string]: number;
  [prop: number]: string; // 报错
}

interface B {
  [prop: string]: number;
  [prop: number]: number; // 正确
} //此处数值索引兼容字符串索引的类型声明。


函数扩展

1、函数参数和返回值 function add(a: number, b: number): number{}
箭头函数定义类型和返回值 const add = (a: number, b: number): number => a + b
2、函数默认的参数 function add(a: number = 10, b: number = 20): number{}
函数可选参数 function add(a?: number, b?: number): number{} 函数默认值和可选参数不能混合使用
3、参数是一个对象如何定义 interface定义
4、函数this类型
ts可以定义this的类型,在js中无法使用,必须是第一个参数定义this的类型
5、函数重载
一个函数里实现增删改查

interface User {
  name: string,
  age: number
}
function add(user: User): User {
  return user
}
console.log(add({ name: '小屋', age: 22 }));
console.log(add(1, 1));
const add = (a: number, b: number): number => a + b
interface Obj {
  user: number[]
  add: (this: Obj, num: number) => void
}
// ts可以定义this的类型,在js中无法使用,必须是第一个参数定义this的类型
let obj: Obj = {
  user: [2, 3, 1],
  add(this: Obj, num: number) {
    this.user.push(num)
  }
}
obj.add(4)
console.log(obj);
let user: number[] = [1, 2, 3]
function findNum(add: number[]): number[] //如果传的是个number类型的数组就是添加
function findNum(id: number): number[] //如果传入id就是单个查询
function findNum(): number[] //如果未传入id就是整个查询
function findNum(ids?: number | number[]): number[] {
  if (typeof ids == 'number') {
    return user.filter(v => v == ids)
  } else if (Array.isArray(ids)) {
    user.push(...ids)
    return user
  } else {
    return user
  }
}
console.log(findNum([4, 5, 6]));

 type A = void | number | never //联合类型时会被忽略

面试题:

interface 与 type 的异同
相同点:interface命令与type命令作用类似,都可以表示对象类型。
区别:
(1)type能够表示非对象类型,而interface只能表示对象类型(包括数组、函数等)。
(2)interface可以继承其他类型,type不支持继承。
(3)继承的主要作用是添加属性,type定义的对象类型如果想要添加属性,只能使用&运算符,重新定义一个类型。而interface为extends
(4) 同名interface会自动合并,同名type则会报错。也就是说,TypeScript 不允许使用type多次定义同一个类型。
(5)interface不能包含属性映射

interface Point {
  x: number;
  y: number;
}

// 正确
type PointCopy1 = {
  [Key in keyof Point]: Point[Key];
};

// 报错
interface PointCopy2 {
  [Key in keyof Point]: Point[Key];
};

(6)this关键字只能用于interface。

// 正确
interface Foo {
  add(num:number): this;
};

// 报错
type Foo = {
  add(num:number): this;
};
class Calculator implements Foo {
  result = 0;
  add(num:number) {
    this.result += num;
    return this;
  }
}

(7)interface无法表达某些复杂类型(比如交叉类型和联合类型),但是type可以。

最后:如果有问题或不理解的地方请大家指出,谢谢大家~

相关推荐

  1. TypeScript 笔记——类型接口

    2024-04-27 19:42:01       13 阅读
  2. 学习TypeScrip3(接口对象类型

    2024-04-27 19:42:01       40 阅读
  3. TypeScript中什么是类类型接口

    2024-04-27 19:42:01       15 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-27 19:42:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-27 19:42:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-27 19:42:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-27 19:42:01       20 阅读

热门阅读

  1. Js简单学习

    2024-04-27 19:42:01       10 阅读
  2. mac上修改git的密码

    2024-04-27 19:42:01       12 阅读
  3. SpringBoot教程(十九) | SpringBoot集成knife4j

    2024-04-27 19:42:01       12 阅读
  4. k8s pod 绑核

    2024-04-27 19:42:01       10 阅读
  5. visual studio code安装Clicknium

    2024-04-27 19:42:01       12 阅读
  6. 前端开发学习笔记(二) : Vue3 常用指令和功能

    2024-04-27 19:42:01       13 阅读
  7. 富格林:可信方针实现安全盈利

    2024-04-27 19:42:01       14 阅读
  8. vue中nextTick函数和react类似实现

    2024-04-27 19:42:01       13 阅读
  9. mysql binlog 中的位点生成逻辑是什么?

    2024-04-27 19:42:01       14 阅读