2017-08-13 60 views
3

介绍问题

我奋力开发编写的打字稿特定功能强大的输入...乐趣+挫折打字稿映射类型

为了便于说明,可以说我在工作部汽车并且具有功能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. 打字稿应该知道每个牌照是在编译时

    字符串
    const licensePlates = registerVehicles({ 
        ferrari: {} 
    }); 
    
    alert(licensePlates.ferrari * 5); // <-- Error, you can't multiple a string 
    

我已经得到接近,但每一个解决方案,我尝试最终失败到m至少满足上述要求之一。帮助我堆栈溢出社区,你是我唯一的希望!

回答

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

+0

这是完美的,非常感谢你! – CodeAndCats

+0

@Magu,我很好奇你是否对https://stackoverflow.com/q/46596846/678505有一些创造性的想法,我认为它甚至可以将TS映射类型提升到更高层次:-) –