3

问题介绍

我正在努力为用 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
    

我已经接近了,但我尝试的每个解决方案最终都无法满足上述要求中的至少一个。帮助我 Stack Overflow 社区,你是我唯一的希望!

4

1 回答 1

3

实用程序类型“记录”可以满足您的需求。有了它,您可以将动态属性从一种类型映射到另一种类型。(在操场上试试):

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

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

更新:它没有很好的记录。但这里是文档的链接,我在这里找到了一个示例

于 2017-08-13T08:41:48.950 回答