打字稿的问题

时间:2018-06-01 22:38:26

标签: typescript

我对Typescript的类型系统有疑问。请问有人帮我吗?

请查看the demo

type Props = { [key: string]: any };

type Config<P extends Props> = {
  hint: string,
  main: (p: P) => string
}

function createDemo<P extends Props>(config: Config<P>): (p: P) => void {
  return (props: P) => {
     document.body.innerHTML +=
      `<div>[${config.hint} ${JSON.stringify(props)}] `
        + `${config.main(props)}</div>`;
  };
}

const demo = createDemo({
  hint: 'showing sum of two values',
  main: ({ x, y }) => x + y
});

demo({ x: 11, y: 22 });
demo({ xx: 11, yy: 22 }); // why do I not get
                          // a Typescript compile-time
                          // error here?!?

我希望最后一个语句demo({ xx: 11, yy: 22 })产生编译时错误。 但打字稿转换器似乎认为它很好。 为什么?我如何将演示更改为类型安全(意味着:使最后一个语句确实导致编译时错误)?

[编辑:1小时后]

如果我向您展示这段代码片段的行为完全符合我的预期(至少在正确配置tsconfig.json的情况下),可能会有所帮助:

function createDemo<P>(action: ((data: P) => void)) {
    return (data: P) => {
        action(data);
    };
}

const demo = createDemo((data: { x: number; y: number }) => {
    document.body.innerText += JSON.stringify(data) + "\n";
});

demo({ x: 11, y: 22 });
demo({ xx: 11, yy: 22 }); // <- ERROR!!!

[编辑 - 2小时后]

好的,谢谢,在阅读了下面的答案之后,我已经了解到,如果我在&#34; createDemo&#34;中添加实际类型签名,事情就会按照我期望的方式运行。调用

然而,坦率地说,我仍然没有完全理解

的类型签名

const f = ({ x, y }) => ...;

被视为

const f = ({ x, y }: { x: any, y: any}) => ...

虽然在我上面的第一个例子中是主函数的类型签名

main: ({ x, y }) => ...

将被视为

main: (p: {}) => ...

而不是

main: ({ x, y }: { x: any, y: any }) => ...

2 个答案:

答案 0 :(得分:0)

查看代码时的一点建议。我不认为你需要P扩展道具。问题是这是Props是一个字典和字符串的字典。

至于你当前的演示没有工作,这是因为createDemo中的main方法没有类型签名,因为它的参数只需添加一个就能解决问题参数,通常默认为any

const demo = createDemo({
  hint: 'showing sum of two values',
  main: ({ x, y }:{x:number, y:number}) => ""+x + y
});

注意添加“”+ x + y是因为你传递了数字,而main的结果应该是一个字符串。

答案 1 :(得分:0)

函数createDemo返回({ [key: string]: any }) => void类型的函数,这就是demo的类型。 demo因此接受一个对象,其中任何字符串作为键,任何类型作为值。

例如,你可以为createDemo提供一个类型参数来解决这个问题:

const demo = createDemo<{x: any, y: any}>({
  hint: 'showing sum of two values',
  main: ({ x, y }) => x + y
});