我对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 }) => ...
答案 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
});