返回具有传入函数参数值的参数类型的函数对象

时间:2021-02-14 11:05:26

标签: typescript dynamic-typing

我想要一个函数,让我们称之为 DummyService ,它会接受一些 definition 对象作为参数并以这些返回函数的参数只能接受参数值的方式返回一堆函数已作为参数传递给 DummyService。请参阅下面的代码示例。知道如何实现这一目标吗?非常感谢。

type Definition = {
    id: string;
    steps: Array<{key: string, callback?: () => void}>
};

const DummyService = (definition: Definition) => {
    return { 
        dummyFn: (step: {key: any}) => { // I need to figure out the type that would allow to pass only certain values that has been passed in `steps` array of `definition`
            console.log(step);
        }
    };
};

const DummyComponent1 = () => {
    const definition = {
        id: "testId1",
        steps: [
            {  key: "key1"},
            {  key: "key2"},
        ],
    };

    const { dummyFn } = DummyService(definition);
    const handler = () => dummyFn({ key: "key1dsfasd" }); // I want this to be invalid - valid key values should be only "key1" or "key2"

    return <div onClick={handler}>test</div>;
}

const DummyComponent2 = () => {
    const definition = {
        id: "testId2",
        steps: [
            {  key: "key3"},
            {  key: "key4"},
        ],
    };

    const { dummyFn } = DummyService(definition);
    const handler = () => dummyFn({ key: "key3" }); // This should be valid - valid key values should be only "key2" or "key4"

    return <div onClick={handler}>test</div>;
}```

1 个答案:

答案 0 :(得分:0)

我们需要使 Definition 成为依赖于步骤数组的泛型。

这里棘手、混乱的部分是将 "key1""key2" 之类的字符串作为它们的字面值处理,而不仅仅是类型 string。为此,我们必须在 as const

之后添加 definition
const definition = {/*...*/} as const;

这将值解释为文字字符串,但它也使定义中的所有内容为 readonly。因此,我们需要在定义 readonlyDefinition 的类型时添加一堆 DummyService,否则我们将在将 readonly 分配给可变类型时出错。

定义如下:

type Definition<Steps extends readonly {key: string, callback?: () => void}[]> = {
    readonly id: string;
    readonly steps: Steps;
};

我们说我们的 Steps extends 是一个数组,我们希望它是一个特定的元组。

我们的 DummyService 看起来像这样:

const DummyService = <Steps extends readonly {key: string, callback?: () => void}[]>(definition: Definition<Steps>) => {
    return { 
        dummyFn: (step: { key: Steps[number]['key'] }) => {
            console.log(step);
        }
    };
};

该类型 Steps[number]['key'] 为我们提供了所有有效的步骤键。作为旁注,我不确定您为什么要传递像 ({key: "key2"}) 这样的参数,而不仅仅是 ("key2")

您现在得到了所有想要的错误,并且在正确调用时没有错误。

Typescript Playground Link

相关问题