// 不使用泛型 function getName01(name: string | number): string | number { return name } console.log(getName01('翠花')) // 翠花 console.log(getName01(123)) // 123
// 使用泛型 function getName02<T>(name: T): T { return name } console.log(getName02<string>('翠花')) // 翠花 console.log(getName02<number>(123)) // 123
结论:使用泛型更灵活。
泛型函数
1 2 3 4
function getName03<T>(name: T): T { return name } console.log(getName03<string>('隔壁老王')) // 隔壁老王
注意:<T> 中的 T 可以是其他合法的字母,建议使用大写字母。
泛型接口
1 2 3 4 5 6 7 8
interface GetName04 { <T>(name: T): T } function getName05<T>(name: T): T { return name } let my_name: GetName04 = getName05 console.log(my_name('小红')) // 小红
const fn = () => {} // const fn: () => void let aa: never = fn() // 不能将类型“void”分配给类型“never”
never 类型的特点
never 类型会从联合类型中移除
1 2 3 4 5 6
type a = unknown | never // unknown type b = any | never // any type c = number | never // number type d = string | never // string type e = object | never // object type f = boolean | never // boolean
never 类型与任意类型的交叉类型都是 never
1 2 3 4 5 6
type g = unknown & never // never type h = any & never // never type i = number & never // never type j = string & never // never type k = object & never // never type l = boolean & never // never
never 可以赋值给任意类型
1 2 3 4 5 6 7
let m: never let n: unknown = m let o: any = m let p: number = m let q: string = m let r: object = m let s: boolean = m
其他类型不能赋值给 never
1 2 3 4
let t: never = 'a' // 不能将类型“string”分配给类型“never” let u: never = 123 // 不能将类型“number”分配给类型“never” let v: never = { a: 1 } // 不能将类型“{ a: number; }”分配给类型“never” let w: never = true // 不能将类型“boolean”分配给类型“never”
enum Type02 { red = 1, green, blue } console.log(Type02.red) // 1 console.log(Type02.green) // 2 console.log(Type02.blue) // 3
或者这样写
1 2 3 4 5 6 7 8
enum Type03 { red, green = 3, blue } console.log(Type03.red) // 0 console.log(Type03.green) // 3 console.log(Type03.blue) // 4
如上,我们定义了 Type02 和 Type03 两个枚举,发现我们不论初始化 red 还是 green,余下的成员都是自动递增的。
字符串枚举
1 2 3 4 5 6 7 8
enum Type04 { red = 'red', green = 'green', blue = 'blue' } console.log(Type04.red) // red console.log(Type04.green) // green console.log(Type04.blue) // blue
字符串枚举没有自增长的行为,字符串枚举可以很好的序列化,字符串枚举允许你提供一个运行时有意义的并且可读的值,独立于枚举成员的名字。。
那么,如果我们只初始化 green 会怎么样?
1 2 3 4 5 6 7
enum Type05 { red, // 正常 green = 'green', blue // 枚举成员必须具有初始化表达式 } console.log(Type05.red) // 0 console.log(Type05.green) // green
let arr_01: number[] = [1, 2, 3] let arr_02: Array<string> = [ 'a', 'b', 'c' ] // 固定数组的长度 let arr_03: Array<number> = new Array(3) let arr_04 = new Array<number>(3)
class Person<T> { public name: string = '老王' private age: number = 30 protected sex: string = '男' getAge() { return this.age } } class Sex extends Person<unknown> { getSex() { return this.sex } } const person = new Person() console.log(person.name) // 老王 // console.log(person.age) // 报错,私有属性,只能在Person类中访问 console.log(person.getAge()) // 30 // console.log(person.sex) // 报错,保护属性,只能在Person类或Sex中访问 const sex = new Sex() console.log(sex.getSex()) //男
类和接口
类使用关键字 implements 实现接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
interface Info { name: string, age: number } class Person implements Info { name: string age: number sex: string constructor(name: string, age: number, sex: string) { this.name = name this.age = age this.sex = sex } getInfo() { return `姓名:${this.name},年龄:${this.age},性别:${this.sex}` } } const person = new Person('翠花', 18, '女') console.log(person.getInfo()) // 姓名:翠花,年龄:18,性别:女
class Person { _name: string get name() { return this._name } set name(n:string) { this._name = n } } const person = new Person() person.name = '老王' console.log(person._name) // 老王
type C = string | number type D = { name: string } | { age: number } const e: D = { name: '老王' } const f: D = { age: 30 } const g: D = { name: '老王', age: 30 }
type可以声明元组类型。
1 2
type H = [ string, number, boolean ] const i: H = [ '老王', 30, true ]