如何基于其他类型定义强类型地图

时间:2020-05-20 09:07:26

标签: typescript

我卡住了,可能需要一些帮助,或者只是从外面看起来焕然一新。

我有这个代码。主要思想是拥有一种描述属性和关联的值类型的类型(请参见类型Person)。然后将其转换为带有元数据的某种映射(请参见const map)。

type Person = {
    firstName: string;
    age: number;
}

type Definition<T> = {
    value: T,
    defaultValue: T
}

type PersonDefintionMap<T> = {
    [key in keyof Person]: Definition<T>
}

const map: PersonDefintionMap<Person[keyof Person]> =
{
    age: { value: 5, defaultValue: 0 },
    firstName: { value: 'test', defaultValue: 'unknown' }
};

它工作得很好,它迫使我填写所有属性,而不允许我输入Person类型中未描述的内容。但是它仍然有两个缺点:

  • 我仍然可以输入错误的类型:
const map: PersonDefintionMap<Person[keyof Person]> =
{
    age: { value: 'I AM NOT A NUMBER', defaultValue: 0 },
    firstName: { value: 'test', defaultValue: 'unknown' }
};
  • 未强制默认值具有与value相同的类型:
const map: PersonDefintionMap<Person[keyof Person]> =
{
    age: { value: 1000, defaultValue: 'MY TURN TO IGNORE THE TYPE' },
    firstName: { value: 'test', defaultValue: 'unknown' }
};

我了解为什么会发生这种情况(我们使用并集定义类型,但我没有找到解决方法。关于如何解决此问题的任何想法?有可能吗?

1 个答案:

答案 0 :(得分:3)

您需要将值的类型(而不是键的类型)传递给Definition

type DefintionMap<T> = {
    [key in keyof T]: Definition<T[key]>
}

// OK
const map: DefintionMap<Person> =
{
    age: { value: 5, defaultValue: 0 },
    firstName: { value: 'test', defaultValue: 'unknown' }
};

// Error as expected
const map2: DefintionMap<Person> =
{
    age: { value: 'I AM NOT A NUMBER', defaultValue: 0 },
    firstName: { value: 'test', defaultValue: 'unknown' }
};

// Error as expected
const map3: DefintionMap<Person> =
{
    age: { value: 1000, defaultValue: 'MY TURN TO IGNORE THE TYPE' },
    firstName: { value: 'test', defaultValue: 'unknown' }
};

Playground