【问题标题】:Return object of functions with argument types of incoming function argument values返回具有传入函数参数值的参数类型的函数对象
【发布时间】:2021-02-14 11:05:26
【问题描述】:

我想要一个函数,我们称它为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>;
}```

【问题讨论】:

    标签: typescript dynamic-typing


    【解决方案1】:

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

    这里棘手、混乱的部分是处理像"key1""key2" 这样的字符串作为它们的字面值,而不是仅仅键入string。为此,我们必须在definition 之后添加as const

    const definition = {/*...*/} as const;
    

    这将值解释为文字字符串,但它也使定义 readonly 中的所有内容。所以我们需要在定义DefinitionDummyService的类型时添加一堆readonly,否则我们将得到将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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 2020-07-30
      • 2019-10-27
      • 1970-01-01
      • 1970-01-01
      • 2021-03-25
      相关资源
      最近更新 更多