枚举中的条件Typescript函数键入

时间:2019-01-07 08:07:38

标签: javascript typescript typescript-typings

我正在创建一个数据库模式,该模式需要每种模型类型的字符串名称,并且需要避免使用类。我的数据库模型由枚举和接口定义:

const enum Models {
  Person = 'Person',
  Vehicle = 'Vehicle',
}

export interface Person {
  firstname: string;
  lastname?: string;
}

export interface Vehicle {
  model: string;
  year?: string;
}

DatabaseModel接口链接modelType名称和相关数据:

export interface DatabaseModel {
  modelType: any;
  data: any;
}

此类型将接口映射到特定的枚举。我不确定如何确切地使用它,但是我认为类型检查才能正常工作。

export type ModelInterfaceMap = {
  Person: Person;
  Vehicle: Vehicle;
}

我已经创建了一个创建数据库模型的函数,如下所示:

export function create(modelType: Models, data ): DatabaseModel {
  return {
    modelType,
    data,
  };
}

我的问题是,如何在上述代码中添加类型,以便可以调用create函数并仅在第一个modelType参数中引用一次模型类型,而仍然获得类型检查数据的所有好处反对它的关联模型?

这应该通过类型检查

var newPerson = create(Models.Person, { firstname: 'John', lastname: 'Doe' });
var newVehicle = create(Models.Vehicle, { model: 'Ford', year: '2018' });

这将使类型检查失败,因为Person界面没有年份

var newPersonFail = create(Models.Person, { firstname: 'John', lastname: 'Doe', year: '2018' });

我尝试使用这种通用类型,但这需要两次编写模型类型;一次是通用类型,一次是在传递modelType时。我希望避免两次指定modelType。

export function create<T>(modelType: Models, data : <T> ): DatabaseModel<T> {...}

1 个答案:

答案 0 :(得分:2)

您需要以通用类型参数(作为枚举文字类型)捕获传递给函数的实际枚举成员。有了这种类型,我们可以根据传入的枚举使用它来索引ModelInterfaceMap以获得data的适当类型:

export function create<T extends Models>(modelType: T, data: ModelInterfaceMap[T]): DatabaseModel {
    return {
        modelType,
        data,
    };
}

var newPerson = create(Models.Person, { firstname: 'John', lastname: 'Doe' });
var newVehicle = create(Models.Vehicle, { model: 'Ford', year: '2018' });

var newPersonFail = create(Models.Person, { firstname: 'John', lastname: 'Doe', year: '2018' });