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可以。
最后:如果有问题或不理解的地方请大家指出,谢谢大家~