使用TypeScript映射类型的乐趣+挫折

时间:2017-08-13 06:32:36

标签: typescript mapped-types

问题简介

我正努力为TypeScript编写的特定函数开发强类型...

为了说明的目的,我们可以说我在机动车部工作并拥有一个功能registerVehicles,可以接受按名称组织的许多车辆的登记详情,并返回每辆车的车牌。

interface RegistrationDetails {
    transmission?: 'manual' | 'automatic';
    wheelCount?: number;
    horsePower?: number;
}

const licensePlates = registerVehicles({
    sportsCar: {
        transmission: 'manual',
        wheelCount: 4,
        horsePower: 762
    },
    motorBike: {
        transmission: 'manual',
        wheelCount: 2
    },
    hoverBoard: {
        // All registration details are optional
    }
});

该函数返回一个对象,其中包含每辆车的名称及其新注册的车牌:

expect(licensePlates).to.eql({
    sportsCar: 'ABCD-1234',
    motorBike: 'SPDY-5678',
    hoverBoard: 'BTTF-2'
});

该功能存在并且运行良好,问题是强力输入

解决方案必须符合以下条件:

  1. 变量licensePlates应该从函数的结果中隐式输入。

  2. 尝试传递不存在的注册详细信息应该在编译时出错。

    registerVehicles({
        car: {
            cowPower: 500 // <-- Spelling mistake, should be horsePower
        }
    })
    
  3. 尝试访问您未注册的车辆的牌照应该在编译时出错:

    const licensePlates = registerVehicles({
        ferrari: {
            horsePower: 562
        }
    });
    
    alert(licensePlates.furrari); // <-- Spelling mistake, should be ferrari
    
  4. TypeScript应该知道每个牌照在编译时都是一个字符串

    const licensePlates = registerVehicles({
        ferrari: {}
    });
    
    alert(licensePlates.ferrari * 5); // <-- Error, you can't multiple a string
    
  5. 我已经接近了,但我尝试的每个解决方案最终都无法满足上述要求中的至少一个。帮助Stack Overflow社区,你是我唯一的希望!

1 个答案:

答案 0 :(得分:3)

实用程序类型“记录”可以满足您的需求。有了它,您可以将动态属性从一种类型映射到另一种类型。 (Try it in the Playground):

function registerVehicles<K extends string>(p: Record<K, RegistrationDetails> ):  Record<K, string> { 
    return null;
}

K类型将是字符串文字类型,例如。 "sportsCar" | "motorBike" | "hoverBoard"

更新:没有详细记录。但这里是a link to the Documentation,我在这里找到了a example