打字稿:取决于字符串参数值的函数返回类型

时间:2019-03-25 20:50:08

标签: typescript

我想为一个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
}

2 个答案:

答案 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;
} */

Playground link to code

答案 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]
  }
}