TypeScript泛型(generic)
2019-11-21 本文已影响0人
不思量q
/**
* generic泛型,给予了开发者创造灵活、可重用代码的能力
* 场景1,假设有个函数A,接受number类型的参数,并返回number类型的值
* 那如果同样的函数B,参数和返回值类型要改变成string,那非得写两个函数么,或者写成any类型?
* 也就是说在静态编写的时候并不确定传入的参数类型,只有运行时传入参数后才可确定
* 这里可以看做需要一个变量,变量代表了传入的类型,然后再返回这个变量,它为一种特殊变量,只用于表示类型而不表示值,即为泛型
*/
function getType(para: string): string {
return para
}
function returnItem<T>(para: T): T {
return para
}
// 编译成JS文件后这俩函数是一样的
// 多个参数类型
function swap<T, U>(tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]]
}
console.log(swap([2, '2oops'])) // ['2oops', 2]
// 假设函数接收一个数组,要求打印数组长度,并返回数组
function getLength<T>(arg: Array<T>) {
console.log((arg as Array<any>).length)
return arg
}
getLength([1,2,3])
// 泛型接口
interface ReturnItemFn<T> {
(para: T): T
}
const Fun1: ReturnItemFn<string> = params => params + '2oops'
console.log(Fun1('hello '))
// 泛型类
class Stack {
private arr: number[] = []
public push(item: number) {
this.arr.push(item)
}
public pop() {
this.arr.pop()
}
}
class GenericStack<T> { // 泛型在类中使用
private arr: T[] = []
public push(item: T) { // 泛型在类的成员函数中使用
this.arr.push(item)
}
public pop() {
this.arr.pop()
}
}
// 泛型约束 <T extends types>
type types = number | string
class TypeStack<T extends types> {
private arr: T[] = []
public push(item: T) {
this.arr.push(item)
}
public pop() {
this.arr.pop()
}
}
const stack1 = new TypeStack<number>()
// const stack2 = new TypeStack<boolean>()
// 泛型约束和索引类型
// 假设设计一个函数接收一个对象和对象的属性作为参数,通过这两个参数返回这两个值
// 直接JS实现可能会写成下面这样,但这是不严谨的
// function getValue(obj, key) {
// return obj[key]
// }
// 然后用TS写成这样?obj为空的场景?
// function getValue(obj: object, key: string) {
// return obj[key] // error
// }
// 正确写法
function getValue2<T extends object, U extends keyof T>(obj: T, key: U) {
console.log(obj[key])
return obj[key]
}
const obj1 = {
name: '2oops',
age: 20
}
getValue2(obj1, "name") // '2oops'
// 使用多重类型进行泛型约束
// 假设泛型被需要被以下两个接口约束
interface first {
doSomething(): number
}
interface second {
doSomethingElse(): string
}
// 或许我们会这样使用
// class interfaceGeneric<T extends first, second> {
// private genericProperty: T
// useT() {
// this.genericProperty.doSomething()
// // this.genericProperty.doSomethingElse() //报错不存在该泛型
// }
// }
// 这时可以将俩接口作为超接口
interface ChildInterface extends first, second {
}
class interfaceGeneric<T extends ChildInterface> {
private genericProperty: T
// 如果直接这样写会报错,这时需要在tsfonfig.json设置下`"strictPropertyInitialization": false`
// 报错参考https://stackoverflow.com/questions/49699067/property-has-no-initializer-and-is-not-definitely-assigned-in-the-construc
useT() {
this.genericProperty.doSomething()
this.genericProperty.doSomethingElse()
}
}
// 泛型和new
// 声明一个泛型其拥有构造函数
function factory<T>(type: {new(): T}): T {
return new type()
}