实战

QueryPrase

type ParseParam<Param extends string> = Param extends `${infer Key}=${infer Value}` ? {
    [K in Key]: Value
} : Record<string, any>


type MergeValue<One, Other> = One extends Other ? One : Other extends unknown[] ? [One, ...Other] : [One, Other]

type MergeParams<OneParams extends Record<string, any>, OtherParams extends Record<string, any>> = {
    readonly [Key in keyof OneParams |  keyof OtherParams] : 
    Key extends keyof OneParams ? Key extends keyof OtherParams ? MergeValue<OneParams[Key], OtherParams[Key]> :OneParams[Key]:Key extends keyof OtherParams ? OtherParams[Key] : never
}

type ParseQueryToString<Query extends string> =  Query extends `${infer Param}&${infer Rest}` ? MergeParams<ParseParam<Param>, ParseQueryToString<Rest>> : ParseParam<Query>


function parseQuery<Querys extends string>(query: Querys): ParseQueryToString<Querys> {
    if (!query || !query.length) return {} as any

    const queryObj = {} as any

    const querys = query.split('&')

    querys.forEach((item) => {
        const [key, value] = item.split('=')

        if (queryObj[key]) {
            if (Array.isArray(queryObj[key])) {
                queryObj[key].push(value)
            } else {
                queryObj[key] = [queryObj[key], value]
            }

        } else {
            queryObj[key] = value
        }

    })
    return queryObj
}

const res = parseQuery('a=1&b=2&c=3&a=9')

KebabCaseToCamelCase

type KebabCaseToCamelCase<Str extends string> = Str extends `${ infer Item } -${ infer Rest } ` ? `${ Item } ${ KebabCaseToCamelCase<Capitalize<Rest>>}`: Str

type Turning = KebabCaseToCamelCase<'system-event-model'>

PartialSpecialKey

将对象的指定属性或方法变为可选

// copy Obj
type Copy<Obj extends Record<string, any>> = {
    [Key in keyof Obj] : Obj[Key]
}

type PartialSpecialKey<
    Obj extends Record<string, any>, 
    Key extends keyof any
> = Copy<Partial<Pick<Obj, Extract<keyof Obj, Key>>> & Omit<Obj, Key>>

type All = {
    name: string
    age: number
    sex: boolean

    output: () => void
}

type PickTwo = PartialSpecialKey<All, 'name' | 'output'>

// output

// type PickTwo = {
//     name?: string
//     output?: () => void

//     age: number
//     sex: boolean
// }

override

// function
declare function Ok(test: string): string;
declare function Ok(test: string): number;

Ok()

// interface
interface T {
    (ok: string): void
    (ok: number): string
}

declare const func: T

// union
type Union = ((name: string) => number) & ((name: number) => string)
declare const un: Union
un()

babel-ts type check

Sourcecode

const { transformFromAstSync } = require('@babel/core');
const parser = require('@babel/parser');
const typeCheckerPlugin = require('./plugin/type-checker2');


const sourceCode = `
    let name: string = 111;
`;

const ast = parser.parse(sourceCode, {
    sourceType: 'unambiguous',
    plugins: ['typescript']
});

const { code } = transformFromAstSync(ast, sourceCode, {
    plugins: [[typeCheckerPlugin, {
        fix: true
    }]],
    comments: true
});

plugin

const { declare } = require('@babel/helper-plugin-utils');

function resolveType(targetType) {
    const tsTypeAnnotationMap = {
        'TSStringKeyword': 'string'
    }
    switch (targetType.type) {
        case 'TSTypeAnnotation':
            return tsTypeAnnotationMap[targetType.typeAnnotation.type];
        case 'NumberTypeAnnotation': 
            return 'number';
    }
}

function noStackTraceWrapper(cb) {
    const tmp = Error.stackTraceLimit;
    Error.stackTraceLimit = 0;
    cb && cb(Error);
    Error.stackTraceLimit = tmp;
}

const noFuncAssignLint = declare((api, options, dirname) => {
    api.assertVersion(7);

    return {
        pre(file) {
            file.set('errors', []);
        },
        visitor: {
            VariableDeclarator(path, state) {
                const errors = state.file.get('errors');

                const idType = resolveType(path.get('id').getTypeAnnotation());
                const initType = resolveType(path.get('init').getTypeAnnotation());

                if (idType !== initType) {
                    noStackTraceWrapper((Error) => {
                        errors.push(path.get('init').buildCodeFrameError(`${initType} can not assign to ${idType}`,Error));
                    })
                }
            }
        },
        post(file) {
            console.log(file.get('errors'));
        }
    }
});

module.exports = noFuncAssignLint;
上次更新:
贡献者: Joe