TypeScript Type-safe Omit Function

前端 未结 4 1914
余生分开走
余生分开走 2021-02-08 20:00

I want to replicate lodash\'s _.omit function in plain typescript. omit should return an object with certain properties removed specified via parameter

4条回答
  •  佛祖请我去吃肉
    2021-02-08 20:28

    Object.keys or for in returns keys as string and excludes symbols. Numeric keys are also converted to strings.

    You need to convert numeric string keys to numbers otherwise it will return the object with string keys.

    function omit,
     K extends [...(keyof T)[]]>(
        obj: T,
        ...keys: K
    ): { [P in Exclude]: T[P] } {
        return (Object.keys(obj)
             .map((key) => convertToNumbers(keys, key)) as Array)
            .filter((key) => !keys.includes(key))
            .reduce((agg, key) => ({ ...agg, [key]: obj[key] }), {}) as {
            [P in Exclude]: T[P];
        };
    }
    
    function convertToNumbers(
        keys: Array,
        value: string | number
    ): number | string {
        if (!isNaN(Number(value)) && keys.some((v) => v === Number(value))) {
            return Number(value);
        }
    
        return value;
    }
    
    
    // without converToNumbers omit({1:1,2:'2'}, 1) will return {'1':1, '2':'2'}
    // Specifying a numeric string instead of a number will fail in Typescript
    

    To include symbols you can use the code below.

    function omit(
        obj: T,
        ...keys: K
    ): { [P in Exclude]: T[P] } {
        return (Object.getOwnPropertySymbols(obj) as Array)
            .concat(Object.keys(obj)
            .map((key) => convertToNumbers(keys, key)) as Array)
            .filter((key) => !keys.includes(key))
            .reduce((agg, key) => ({ ...agg, [key]: obj[key] }), {}) as {
            [P in Exclude]: T[P];
        };
    }
    

提交回复
热议问题