typescript6 - advanced typing

cross type

  1. Merge multiple types into a new type that has all the properties of the type
interface A{
    
    
    name:string
}

interface B{
    
    
    age:number
}
type C=A & B
const c:C={
    
    
    name:'jack',
    age:19
}
console.log(c)

union type

  1. Indicates that one of the
// 表示可以是string或者number
const getLengthFunc=(content:string|number):number=>{
    
    
    if(typeof content==='string') return content.length
    else return content.toString().length
}
console.log(getLengthFunc('123')) // 3
console.log(getLengthFunc(123)) // 3

type protection

  1. Type guards are expressions that are checked at runtime to ensure that the type
const getRandomValue=()=>{
    
    
    const num=Math.random()
    if(num>0.5) return '123'
    else return 123
}
const item=getRandomValue();
function isString(value:string|number):value is string{
    
    
    return typeof value === 'string'
}
if(isString(item)){
    
    
    console.log(item.length)
}else {
    
    
    console.log(item.toFixed())
}
  1. typeof type protection, the type can only be one of string/number/boolean/symbol
  2. instanceof type protection
class CreatClass1{
    
    
    public name='jack'
}
class CreatClass2{
    
    
    public age=20
}
function getRandomClass(){
    
    
    const random=Math.random()
    return random>0.5?new CreatClass1():new CreatClass2()
}
const item=getRandomClass()
if(item instanceof CreatClass1){
    
    
    console.log(item.name)
}else {
    
    
    console.log(item.age)
}

type alias

  1. Type names can be redefined
  2. Type aliases can be nested
  3. You cannot use extends | interface when aliasing an interface
type TypeString=string
let str:TypeString;
type PositionType<T>={
    
    
    x:T,
    y:T,
}
const position:PositionType<number>={
    
    
    x:1,
    y:1
}
console.log(position)
type Childs<T>={
    
    
    current:T,
    child?:Childs<T>
}
const c:Childs<string>={
    
    
    current:'first',
    child:{
    
    
        current:'second',
        child:{
    
    
            current:'third'
        }
    }
}
console.log(c)
type Direction = 'first' | 'second' | 'third';
function getDirction(direction:Direction){
    
    
    return direction.substr(0,1)
}
// 只能传入 'first' | 'second' | 'third'中的一个
console.log(getDirction('first'))

Discriminated Union

  • Has common singleton type properties—discernible traits
  • A type alias contains unions of those types
  • type guard on this property
interface Square{
    
    
	kind:'Square',
	size:number
} 
interface Rectangle{
    
    
	kind:'Rectangle',
	height:number,
	width:number 
} 
interface Circle{
    
    
	kind:'Circle',
	radius:number 
}
 
 /**  * kind 作为唯一特征,用来做判断  *  */
 type Shape=Square | Rectangle |Circle; 
 function assertNever(value:never):never{
    
    
     throw Error('Unexpected object'+ value) } function getArea(c:Shape):number{
    
    
     switch (c.kind){
    
    
         case 'Square': return c.size;break;
         case 'Rectangle': return c.width*c.height;break;
         case 'Circle': return Math.PI*c.radius**2;break;
         default: return assertNever(c)
     } } const circle:Circle={
    
    
     kind:'Circle',
     radius:20 } console.log(getArea(circle))

polymorphic this type

  1. That is, a subtype of an interface or a class
  2. Return the current instance object when the method ends in the parent type, so that the subclass does not have this method but can still call the method of the parent class
class Counter{
    
    
    constructor(public count:number=0) {
    
    
    }
    public add(value:number){
    
    
        this.count+=value;
        return this;
    }
    public subtract(value:number){
    
    
        this.count-=value;
        return this;
    }
}
const counter=new Counter(10)
counter.add(1).subtract(2)
console.log(counter)
// Counter {count: 9}
class PowCounter extends Counter{
    
    
    constructor(count:number) {
    
    
        super(count);
    }
    public pow(value:number){
    
    
        this.count=this.count**value;
    }
}
const powCounter=new PowCounter(20)
powCounter.pow(2)
powCounter.add(100)
console.log(powCounter)
// PowCounter {count: 500}

index type

  • keyof index type query operator
  • T[K] index access operator, that is, whether there is K on T
  • Can check whether there is a corresponding key-value pair on the object
interface InfoI{
    
    
    name:string,
    age:number
}
let infoProps:keyof InfoI
// infoProps 只能是接口定义的键值
infoProps='name'
infoProps='age'

function getValue<T,K extends keyof T>(obj:T,names:K[]):T[K][]{
    
    
    return names.map(item=>obj[item])
}
const infoObj={
    
    
    name:'jack',
    age:20
}
const infoValue:(string|number)[]=getValue(infoObj,['name','age'])
console.log(infoValue)

mapping type

  • create a new type from an old type
  • TS built-in Readonly read-only and Partial optional
type MapToPromise<T>={
    
    
    [K in keyof T]:Promise<T[K]>
}
type Tuple=[number,string,boolean]
type promiseTuple=MapToPromise<Tuple>
let tuple:promiseTuple=[
    new Promise((resolve) => resolve(1)),
    new Promise((resolve) => resolve('1')),
    new Promise((resolve) => resolve(false)),

]
console.log(tuple)

unknown

  • Any type can be assigned to the unknown type
  • If there is no type assertion or type refinement based on control flow, unknown cannot be assigned to other types
  • Nothing can be done on it without type assertion or type refinement based on control flow
  • The intersection type of unknown and any other type, returns the other type
  • The joint type composed of unknown and other types (except any is any) is equal to unknown
  • never is a subtype of unknown
  • keyof unknown is never type
  • You can only perform wait or wait operations on unknown, and no other operations can be performed
  • A value of unknown type cannot access its properties, cannot be called as a function, and cannot be used as a class to create an instance
  • If the unknown type is used for mapping, no type will be mapped

condition type

  • Similar to the ternary operator
  • T extends U ? X : Y
type Type<T>=T extends string ? string : number
let type:Type<string>='a'
// 分布式条件类型
type Type2<T>=
    T extends string ? string :
    T extends number ? number :
    T extends ()=>void ? ()=>void :
    object;
type type2=Type2<((()=>void) | number)>
// type2类型为()=>void | number
  • Type inference infer for conditional types
type Type1<T>=T extends Array<infer U> ? U : T;
type type=Type1<string[]>
  • Exclude intersection | Extract union
type Type1=Exclude<'a'|'b'|'c', 'a'>
// Type1类型为'b'|'c'
type Type2=Extract<'a'|'b'|'c', 'a'>
// Type2类型为'a'
  • NonNullable removes null and undefined | ReturnType returns the return type of the function
type Type1=NonNullable<string | number | null | undefined>
// Type1类型为string | number
type Type2=ReturnType<()=>string>
// Type2类型为string
  • InstanceType infers the type of the class from the type
class AClass{
    
    
    constructor(public name:number=10) {
    
    
    }
}
type Type1=InstanceType<typeof AClass>
type Type2=InstanceType<any>

Guess you like

Origin blog.csdn.net/weixin_64925940/article/details/126808332