Cover
📄

【TS技巧】通过对象推导出联合类型

2023-04-25 1 min read

首先,我们给出下面👇🏻这段代码,`fruitCount`的每个属性值类型都是`number`,我们期望由它衍生出一个`singleFruitCount`对象

export const fruitCount = {

apple: 1,

pear: 4,

banana: 26,

}

/**

  • 类型是一个对象
  • key对应fruitCount的key
  • value 是 number 类型
  • **/

    type SingleFruitCount

    =

    any//怎么定义❓

    const singleFruitCount: 

    SingleFruitCount

    = {

    banana: 12,

    }

    你可能会想到以下两个方案

    //

    方案1

    type SingleFruitCount = {

    [k in keyof typeof fruitCount]?:number

    }

    //

    方案2

    type SingleFruitCount =

    | {

    apple: number;

    }

    | {

    banana: number;

    }

    | {

    pear: number;

    }

    _方案1_看起来更简洁并且可以满足我们的需要,但是他是一个`partial`并不是一个`union`类型,`union`跟`partial`相比有更多的转换能力,我们会在下一个`tips`中体现。

    让我们回到_方案2_,_方案2_虽然能满足需求,但是看起来并不那么优雅,所以让我们改进一下,先从`fruitCounts`对象中创建一个`FruitCount`类型,然后我将衍生出一个新的类型`NewSingleFruitCount`

    type FruitCounts = typeof fruitCounts

    type NewSingleFruitCount = {

    [K in keyof FruitCounts]: {}

    }

    /**

    它将 FruitCounts 的每个属性值设置为一个空对象

    因此,当我们使用它时,TypeScript将期待一个像这样的效果👇🏻

    **/

    const singleFruitCount: NewSingleFruitCount = {

    apple: {},

    pear: {},

    banana: {}

    }

    但是我们期望属性值的类型是`number`,我们进行下一步改进

    type NewSingleFruitCount = {

    [K in keyof FruitCounts]: {

    [K2 in K]: number

    }

    }

    //效果如下👇🏻

    const singleFruitCount: NewSingleFruitCount = {

    apple: {

    apple: 2,

    },

    pear: {

    pear: 4,

    },

    banana: {

    banana: 26,

    },

    }

    最后,我们通过映射`NewSingleFruitCount`类型,来获取真实的值

    type NewSingleFruitCount = {

    [K in keyof FruitCounts]: {

    [K2 in K]: number

    }

    }[keyof FruitCounts]

    这样就可以获取到真实的结果🎉

    const singleFruitCount: NewSingleFruitCount = {

    apple: 2,

    }

    const singleFruitCount:SingleFruitCount = {}//期望 ts 能够报错,但是它并不会报错

    type SingleFruitCount = {

    [k in keyof typeof fruitCount]?:number

    }

    End of file