例子:
interface Point2D { x: number; y: number }
interface Point3D { x: number; y: number; z: number }
interface Point2D { x: number; y: number }
// 继承 Point2D
interface Point3D extends Point2D {
z: number
}
用type实现继承效果
// & 与连接符: 既要满足前面的也要满足后面的
// | 或连接符: 满足其中一个即可
type Student = {
score: number
sleep: () => void
} & Person
const s2: Student = {
username: '刘狄威',
age: 28,
gender: '未知',
sayHi() {
console.log('大嘎好!')
},
score: 80,
sleep() {
console.log('我在睡觉')
},
}
元组类型是另一种类型的数组,它确切地知道包含多少个元素,以及特定索引对应的类型
let position: [number, number] = [39.5427, 116.2317]
根据初始化的值 定属性。
发生类型推论的 2 种情况:
// 变量 age 的类型被自动推断为:number
let age = 18
// 函数返回值的类型被自动推断为:number
function add(num1: number, num2: number): number {
return num1 + num2
}
任意的 JS 字面量(比如,对象、数字等)都可以作为类型使用
字面量: { name: 'jack' } [] 18 20 'abc' false function() {}
使用模式:字面量类型配合联合类型一起使用
使用场景:用来表示一组明确的可选值列表
比如,在贪吃蛇游戏中,游戏的方向的可选值只能是上、下、左、右中的任意一个
// 使用自定义类型:
type Direction = 'up' | 'down' | 'left' | 'right'
function changeDirection(direction: Direction) {
console.log(direction)
}
// 调用函数时,会有类型提示
changeDirection('up')
枚举的功能类似于字面量类型+联合类型组合的功能,也可以表示一组明确的可选值
枚举:定义一组命名常量。它描述一个值,该值可以是这些命名常量中的一个
// 创建枚举
enum Direction { Up, Down, Left, Right }
// 使用枚举类型
function changeDirection(direction: Direction) {
console.log(direction)
}
// 调用函数时,需要应该传入:枚举 Direction 成员的任意一个
// 类似于 JS 中的对象,直接通过 点(.)语法 访问枚举的成员
changeDirection(Direction.Up)
解释:
1. 使用 enum 关键字定义枚举
2. 约定枚举名称以大写字母开头
3. 枚举中的多个值之间通过 , (逗号)分隔
4. 定义好枚举后,直接使用枚举名称作为类型注解
可以键值对相互查找。
// 枚举: 如果不设置值, 默认从 0 开始
// type Direction = '上' | '下' | '左' | '右'
enum Direction {
Up = 'Up',
Down = 'Down',
Left = 'Left',
Right = 'Right'
}
// enum Direction {
// Up, // 0
// Down, // 1
// Left, // 2
// Right // 3
// }
// 枚举内部还做了一个事情: 可以通过键找值, 也可以通过值找键
// console.log(Direction)
function changeDirection(direction: Direction) {
console.log(direction)
}
changeDirection(Direction.Up)
changeDirection(Direction.Down)
changeDirection(Direction.Left)
changeDirection(Direction.Right)
// 后端给前端的一些属性都是 0 1 2 3 这样的数字, 例如: 性别
// 如果后端给的是 100 上 101 下 102 左 103 右
原则:不推荐使用 any!这会让 TypeScript 变为 “AnyScript”(失去 TS 类型保护的优势) 因为当值的类型为 any 时,可以对该值进行任意操作,并且不会有代码提示
let obj: any = { x: 0 }
obj.bar = 100
obj()
const n: number = obj
// 页面上有一个 id 为 link 的 a 标签
// 我们知道它是 a 标签
// 但是 TS 不知道
// document.getElementById 的返回值是 HTMLElement
// 而 HTMLElement 身上没有 href
// 类型断言: 强行指定获取到的结果类型
const a = document.getElementById('link') as HTMLAnchorElement
const box = document.getElementById('box') as HTMLDivElement
const pp = document.getElementById('pp') as HTMLParagraphElement
const img = document.getElementById('avatar') as HTMLImageElement
// img.src
// const result = document.createElement('img')
// console.log(a.href)
// if (a) {
// console.log(a.href)
// }
// a && a.href
// 总结: 当函数获取到的结果类型较为宽泛时, 我们又知道具体类型, 就可以使用断言强行指定类型
function id(value: number): number { return value }
function id(value: any): any { return value }
function id(value: Type): Type { return value }
function id(value: T): T { return value }
const num = id(10)
const str = id('a')
1. 语法:在函数名称的后面添加 <> (尖括号),尖括号中指定具体的类型,比如,此处的 number
2. 当传入类型 number 后,这个类型就会被函数声明时指定的类型变量 Type 捕获到
3. 此时,Type 的类型就是 number,所以,函数 id 参数和返回值的类型也都是 number
// 省略 调用函数
let num = id(10)
let str = id('a')
因为有ts有类型推断机制,我们可以省略类型,但是要注意, 当编译器无法推断类型或者推断的类型不准确时,就需要显式地传入类型参数 。
在正常情况下,泛型可以代表多种类型,这会导致无法访问任何属性。就像你调用泛型函数传入一个string类型的参数,而你却不能用length属性,那么就要加约束。
// 指定更加明确的类型: T类型的数组, val 确定就是一个数组了, 所以可以用 length
function getIds(val: T[]) {
console.log(val.length) // val: 已经明确是一个数组了, 所以自然会有数组的所有属性
return val
}
// 创建一个接口
interface ILength { length: number }
// Type extends ILength 添加泛型约束
// 解释:表示传入的 类型 必须满足 ILength 接口的要求才行,也就是得有一个 number 类型的 length 属性
function id(value: Type): Type {
console.log(value.length)
return value
}
function getId(val: T) {
if (typeof val === 'string') {
console.log(val.length) // 报错: T 是一个未知的类型, 所以无法得知它到底有没有 length
} else if (typeof val === 'number') {
val.toFixed()
}
return val
}
// 定义接口
interface ILength {
length: number
// sayHi: () => void
}
// 添加约束: 给泛型找爸爸
function getId(val: T) {
console.log(val.length)
return val
}
console.log(getId('abcd'))
// console.log(getId(123))
// console.log(getId(true))
泛型的类型变量可以有多个,并且类型变量之间还可以约束(比如,第二个类型变量受第一个类型变量约 束) 比如,创建一个函数来获取对象中属性的值:
function getProp(obj: Type, key: Key) {
return obj[key]
}
let person = { name: 'jack', age: 18 }
getProp(person, 'name')
泛型接口:接口也可以配合泛型来使用,以增加其灵活性,增强其复用性
interface IdFunc {
id: (value: Type) => Type
ids: () => Type[]
}
let obj: IdFunc = {
id(value) { return value },
ids() { return [1, 3, 5] }
}
{
// 泛型接口 为了复用
interface Student {
id: number
name: T
hobby: T[]
}
let s1: Student = {
id: 123,
name: '小刘',
hobby: ['抽烟', '喝酒', '写圣杯布局']
}
const s2: Student = {
id: 123,
name: 0,
hobby: [1, 2, 3, 4]
}
const arr1: number[] = [1, 2, 3]
const arr2: Array = [1, 2, 3]
const arr3: Array = ['1', 'a', 'c']
// arr2.push('abc')
// arr3.push(123)
}