我想为一个JavaScript库编写类型,该JavaScript库根据传递给它的字符串创建一个函数对象。
该功能应该是这样的:
function createResource(name: string): { /* How to write these types? */ } {
return {
[`create${name}`]: () => {},
[`update${name}`]: () => {},
}
}
这个想法是给函数一个字符串(例如“ todo”),该函数将返回一个对象
{
createTodo: (todo: Todo) => void,
updateTodo: (todo: Todo) => void
}
答案 0 :(得分:1)
如果/ microsoft/TypeScript#40336合并到母版中时(希望适用于TS4.1),您将能够使用模板字符串类型来表示串联"create"
时发生的情况和"update"
到为name
传递的字符串中。看起来像这样:
function createResource<T extends string>(name: T) {
return {
[`create${name}`]: () => { },
[`update${name}`]: () => { },
} as { [K in `${"create" | "update"}${T}`]: () => void };
}
产生如下输出:
const resource = createResource("Todo");
/* const resource: {
createTodo: () => void;
updateTodo: () => void;
} */
请注意,`create${name}`
不会产生"createTodo"
,除非name
是"Todo"
,且其首字母为"T"
。可以使用capitalize
修饰符在类型系统中将"todo"
转换为"Todo"
,但是您的实现也需要更改...类似:
const cap = (s: string) => s.charAt(0).toUpperCase() + s.slice(1);
function createResource2<T extends string>(name: T) {
return {
[`create${cap(name)}`]: () => { },
[`update${cap(name)}`]: () => { },
} as { [K in `${"create" | "update"}${capitalize T}`]: () => void };
}
const resource2 = createResource2("todo");
/* const resource2: {
createTodo: () => void;
updateTodo: () => void;
} */
答案 1 :(得分:0)
只需用实现定义对象(我假设您想将void
替换为实际的实现或函数调用):
const functions = {
createTodo: (todo: Todo) => void,
updateTodo: (todo: Todo) => void
}
,然后您的createResource
函数将如下所示:
function createResource(name: string) {
const createFuncName = `create${name}`
const updateFuncName = `update${name}`
return {
[createFuncName]: functions[createFuncName],
[updateFuncName]: functions[updateFuncName]
}
}