Simple example about Generics
function simpleArrayNumber(...args:number[]):number[]{ return [...args] } function simpleArrayString(...args:string[]):string[]{ return [...args] }
Instead, we need a way of capturing the type of the argument in such a way that we can also use it to denote what is being returned. Here, we will use a type variable, a special kind of variable that works on types rather than values.
function simpleArray<T>(...args:T[]):T[]{ return [...args] }
Use generic function:
let myArrayNumber = simpleArray<number>(0,1,2,3) let myArrayString = simpleArray<string>("a","b") console.log(myArrayNumber) //[ 0, 1, 2, 3 ] console.log(myArrayString) //[ 'a', 'b' ]
Generic with Array
function myArray<T>(arg: Array<T>): Array<T> { console.log(arg.length) return arg } let myArray1 = myArray<string>(["hello","world"]) console.log(myArray1) //[ 'hello', 'world' ]
Generic Types , Generic Interface
Method 1: we can define a type:
type myType = <T>(arg: Array<T>) => Array<T> let myFunc:myType = myArray let myArray2 = myFunc<string>(["hello","world"]) console.log(myArray2) //[ 'hello', 'world' ]
Method 2: use interface
interface myGeneric{ <T>(arg: Array<T>): Array<T> } let MyFunc:myGeneric = myArray let myArray3 = MyFunc<string>(["hello","world"]) console.log(myArray3) //[ 'hello', 'world' ]
Method 3: generic interface
interface myGenericFn<T>{ (arg: Array<T>): Array<T> } let MyFunc2:myGenericFn<string> = myArray let myArray4 = MyFunc2(["hello","world"]) console.log(myArray4) //[ 'hello', 'world' ]
When we use myGenericFn
, we now will also need to specify the corresponding type argument (here: string
), effectively locking in what the underlying call signature will use.
Generic Classes
class myClass<T> { value: T run:(a:T,b:T)=>T } var myVar = new myClass<string>() myVar.value = "hello" myVar.run = function(a,b){ return a+b } console.log(myVar.run("hello"," world"))
Note: Static members cannot reference class type parameters.
class Base<T> { static prop: T; //error TS2302: Static members cannot reference class type parameters. }
Generic Constraints
Use the extends keyword to denote the constraint:
interface hasLength { length: number } function func1<T extends hasLength>(arg: T): T { //type T must has length property console.log(arg.length) return arg }
Using Type Parameters in Generic Constraints
You can declare a type parameter that is constrained by another type parameter. For example, here we’d like to get a property from an object given its name. We’d like to ensure that we’re not accidentally grabbing a property that does not exist on the obj, so we’ll place a constraint between the two types:
function getProperty<T, K extends keyof T>(obj: T, key: K) { return obj[key]; } let x = { a: 1, b: 2, c: 3, d: 4 } getProperty(x, "a")
Using Class Types in Generics
//Method 1 function createInstance<T>(c: { new (): T }): T { return new c(); } //Method 2 function createInstance2<T>(c: new ()=> T): T { return new c(); } console.log(createInstance(myClass)) //myClass {} console.log(createInstance2(myClass)) //myClass {}