高级ts方法封装

80 阅读2分钟

const peopls: People = {
    name: 'tom',
    age: 123,
    cardId: '123123012931'
}



/**
 * 限制数组类型最大长度
 */

type ArrayMax<T extends number, Type extends any = any, A extends any[] = []> = A['length'] extends T ? A : ArrayMax<T, Type, [Type, ...A]>

const testArrayMax: ArrayMax<2, number | string> = [2,2];

/**
 * 获取Promise函数的返回值类型
 * 关键词: infer
 */

type ReturnPromiseValue<T extends (...argv: any) => any> = T extends (...args: any) => Promise<infer D> ? D : never
declare function awaitTime(): Promise<{ time: number, value: 1 }>
type promiseValue = ReturnPromiseValue<typeof awaitTime>

/**
 * 判断类型是否为number
 */
type isNumber<T> = T extends number ? true : false;
type isNumberResult = isNumber<1>;
type isNumberResult2 = isNumber<'1'>;

/**
 * 元组转合集
 */
type TupleToUnion<T extends any[]> = T extends Array<infer R> ? R : never
type TupleToUnion2<T extends any[]> = T[number]
type TupleToUnionResult = TupleToUnion<[123, '456', true]>;

/**
 * 判断传入的对象是否包含指定的key
 */
type isIncludeKey<T extends object, K extends string> = K extends keyof T ? true : false
type isIncludeKeyResult = isIncludeKey<{ name: string, age: number, cardId: number }, 'cardId'>
type isIncludeKeyResult2 = isIncludeKey<{ name: string, age: number, cardId: number }, 'cardId2'>

/**
 * 移除类型中的指定key
 * 功能等同于Omit
 */
type MyOmit<T, Keys extends keyof T> = {
    [k in keyof T as k extends Keys ? never : k]: T[k]
}
type myOmitResult = MyOmit<{ name: string, age: number, cardId: number }, 'cardId'>

/**
 * 函数类型重构
 */
declare function dinner(hotPot: string): 300
declare function dinner(hotPot: string, barbecue: string): 600
declare function dinner(hotPot: string, barbecue: string, other: string): 900
const money1 = dinner('', 'awd');
const money2 = dinner('', 'awd', '')

/**
 * 模板字符串类型
 */

type Long = 'en' | 'cn' | 'pt';
type Ids = 'cardid' | 'email';
type MergeIds = `${Long}_${Ids}`;

/**
 * 实现jQuery结构
 */
interface jQuery {
    (): any
    ajax: () => any
}
const jQuery: jQuery = () => {

}
jQuery.ajax = () => {

}

interface People {
    name: string,
    age: number,
    cardId: string,
    email?: string,
    address?: string
}

/**
 * 移除所有可选项
 * 映射修饰符
 * @returns 
 */
type RemoveOptional<T> = {
    [k in keyof T]-?: T[k]
}

/**
 * 根据参数设置可选项
 * @returns 
 */
type Optional<T, Key extends keyof T> = MergeInterface<{
    [k in keyof T as k extends Key ? never : k]: T[k]
} & {
        [k in Key]?: T[k]
    }>

type Optional2<T, Key extends keyof T> = {
    [k in keyof T as k extends Key ? never : k]: T[k]
} & {
        [k in Key]?: T[k]
    }

/**
 * 两个类型合并成一个
 */

type MergeInterface<T> = {
    [k in keyof T]: T[k]
}

type AllRequirePeople = RemoveOptional<People>
type OptionalPeople = Optional<People, 'age' | 'cardId'>
type OptionalPeople2 = Optional2<People, 'age' | 'cardId'>

/**
 * 获取数组里的所有值
 */
const names = ['tom', 'job'] as const;
type NumeInterface = typeof names;
/**
 * 根据上述的names生成对应私有,公有方法
 */
type CreateMethods<T extends readonly string[]> = MergeInterface<{
    [k in keyof T as T[k] extends string ? (k extends string ? `_${T[k]}` : never) : never]: T[k]
} & {
        [k in keyof T as T[k] extends string ? `get${Capitalize<T[k]>}` : never]: () => string
    } & {
        [k in keyof T as T[k] extends string ? `set${Capitalize<T[k]>}` : never]: (value: string) => void
    }>

type NamesMethods = CreateMethods<NumeInterface>

type ConversionValueMethod<T> = {
    swiper: () => T
}
/**
 * 更高级的入参类型限制,
 * 设置传进来的对象必须有某个固定的方法
 */
type ConversionValue<T> = ConversionValueMethod<T> extends {
    swiper: () => infer Res
} ? ConversionWriteValue<Res> : never

type ConversionWriteValue<T> = {
    swiper: () => T
}
const conversionValueMethods = {
    swiper() {
        return {
            version: '5.5.13',
            init(){},
            swiperTo(index: number){},
            a: false
        }
    },
    scrollJs: () => ({
        version: '3.4.5',
        scrollTo(scroll: number) {},
        desctory(){}
    })
} 
const getSwiper = <Data extends object>(state: ConversionValue<Data>) => {
    return function call<Key extends keyof Data>(key: Key, value: Data[Key]) {  }
}

const swiperCall = getSwiper(conversionValueMethods);
swiperCall('a', true)

/**
 * 前置不定量参数
 */
declare function addImpl<Params extends any[]>(...args: [
    ...Params,
    (...args: Params) => void
]): void;

addImpl('name', 123, (name, age) => {

})

/**
 * 根据入参,动态匹配所需参数以及返回值
 */
interface PeopMethods {
    updateName: (name: string) => Promise<{ success: boolean, name: string }>
    createName: (name: string, gender: number) => Promise<{ success: boolean, name: string, uid: number }>
    removeName: (uid: number) => Promise<{ success: boolean }>
}
declare function callPeopleMethods<Key extends keyof PeopMethods>(name: Key, ...params: Parameters<PeopMethods[Key]>): ReturnType<PeopMethods[Key]>
callPeopleMethods('createName', 'tom', 18);
callPeopleMethods('updateName', 'awd')

/**
 * 防止获取object时候输入错误key
 */
declare function getPrototype<T, k extends keyof T>(data: T, key: k): void
getPrototype(peopls, 'age');

/**
 * 修改函数内的this执行,实现类型vue options api函数的效果
 */

declare function createVue<D, M, T = D & M>(options: {
    data: D,
    methods?: M & ThisType<D & M>,
    mounted?: (this: T) => void
}): M & D;
const c = createVue({
    data: peopls,
    methods: {
        getName() {
            return this.name;
        },
        say() {
            this.address
            this.getName
        }
    },
    // mounted方法如果想要使用this.methods内的方法就必须定义在methods声明的下面,不然ts无法读取到method类型
    mounted() {
        this.address
    },
})
c.getName

/**
 * 实现类似react ui库material-ui中makeStyles的类型声明
 * @param styles 
 */
declare function makeStyles<T extends Record<string, ColorProps | (() => ColorProps)>>(styles: T): { [name in keyof T]: any };
interface ColorProps {
    fontSize?: number
    width?: number
    height?: number
    background?: string,
    display?: 'flex' | 'none' | 'block'
}
const thems = makeStyles({
    root: {
        fontSize: 20,
        width: 200,
        height: 200
    },
    theme: () => {
        return {
            background: 'red'
        }
    }
})


/**
 * 简单的 Vue 类型
 */

type GetComputed<TComputed> = {
    [key in keyof TComputed]: TComputed[key] extends () => infer Result ? Result : TComputed[key];
};
interface VueOptionModal<TData, TComputed, TMethods> {
    data?: () => TData
    computed?: TComputed & ThisType<TData & GetComputed<TComputed> & TMethods>;
    methods?: TMethods & ThisType<TData & GetComputed<TComputed> & TMethods>;
}

declare function SimpleVue<D, C extends object, M extends object>(options: VueOptionModal<D, C, M>): unknown
SimpleVue({
    data() {
        return {
            gender: 2
        }
    },
    computed: {
        age() {
            return 2
        },
        fullname() {
            return `gender+ ${this.gender}`
        },
    },
    methods: {
        getName() {
            this.getName
            this.gender
            this.age
            this.fullname
        }
    },
})

/**
 * 实现类似于zustand的效果
 */
interface StoreState {
    name: string,
    age: number,
    success: boolean
}
declare type StateCreator<T> = (set: (params: {
    [k in keyof T]+?: T[k]
}) => void, get: () => T) => T;

interface StateApi<T> {
    getState: () => T
    setState: Parameters<StateCreator<T>>[0]
}

declare function createStore<T extends (...args: any) => any>(fn: T): StateApi<ReturnType<T>>;

const storeStateCreator: StateCreator<StoreState> = (set, get) => {
    get().age
    set({
        name: 'awd',
        age: 2
    })
    return {
        name: '',
        age: 23,
        success: false
    }
};
const store = createStore(storeStateCreator);

type StoreValues<T> = {
    getState: () => T
}
type Store<T> = StateApi<T> extends {
    getState: () => infer Values
} ? StoreValues<Values> : never
declare function useZustandStore<State extends object>(store: Store<State>): () => State
declare function useZustandStore<State extends object, Selector extends (s: State) => any>(store: Store<State>, selector?: Selector): ReturnType<Selector>
const useStoreValue = useZustandStore(store);
// useStore().age
const useStoreUserName = useZustandStore(store, s => s.age);
const useStore = <T = StoreState>(
    selector?: (state: StoreState) => T,
): T => useZustandStore(store, selector);
useStore().name
const ne = useStore(s => s.name);

/**
 * 特殊zustand的调用方式
 * @param store 
 */
declare function bindZusStore<
    State extends object,
>(store: Store<State>): <Key extends Array<keyof State>>(
    keys: [...Key],
    watch: (
        data: { [k in keyof Key]: State[Key[k]] }
    ) => Promise<boolean> | boolean
) => void

const storeZusConfig = bindZusStore(store);
storeZusConfig(['name', 'age', 'success'], (c) => {
    const [a, b, cd] = c;
    return true
})

/**
 * 收集run函数每次调用所传入的类型并在调用end函数时候,传给end函数
 */
const util = <Params extends any[] = []>() => {
    return {
        run<T>(data: T) {
           return util<[...Params, T]>();
        },
        end(fn: (c: Params) => void) { }
    }
}
const cdd = util().run('awdawd').run(213).run('xxxx').run({ name: 'tom', age: 23 });
cdd.end(c => {})