typescript - 打字稿条件属性未检测到错误的功能参数
问题描述
条件类型应该允许智能属性,我已经设法从@jcalz 获得关于这个问题的先前版本的帮助。不幸的是,虽然这个问题得到了解决,但我仍然可以获得我想要的类型严格性。下面的最后一行应该会导致错误:
interface Props<T, S extends boolean = boolean> {
value: T;
isString: S;
submit: S extends true ? (arg: string) => void : (arg: T & {}) => void;
}
interface FalseProps<T> {
value: T;
isString: false;
submit: (arg: T & {}) => void;
}
interface TrueProps<T> {
value: T;
isString: true;
submit: (arg: string) => void;
}
function fancyFunction<T>(props: Props<T>): void
function fancyFunction<T>(props: TrueProps<T> | FalseProps<T>): void {
if (props.isString === true) {
props.submit('return a string');
} else if (props.isString === false) {
props.submit(props.value);
}
}
const args1 = {
value: 2,
isString: true,
submit: (arg: string) => console.log(arg),
};
fancyFunction(args1);
const args2 = {
value: { id: 2 },
isString: false,
submit: (arg: { id: number }) => console.log(arg),
};
fancyFunction(args2);
const args3 = {
value: { id: 2 },
isString: false,
submit: (arg: string) => console.log(arg),
};
fancyFunction(args3);
打字稿代码可以在这里找到。
解决方案
与您的其他问题一样,fancyFunction()
它只是通用 inT
而不是S
in Props<T, S>
。当您只使用Props<T>
时,您会得到一个isString
属性与其属性不相关的类型submit
。它们都是联合体,没有什么可以阻止isString
whilefalse
是submit
type (arg: string)=>void
。所以你没有错误。
与其尝试用多个类型参数来挽救这个条件类型的东西,为什么不将实现签名公开fancyFunction()
为它的调用签名呢?该类型TrueProps<T> | FalseProps<T>
是一个具有鉴别属性的鉴别联合isString
,它在函数的调用端和实现端都按照您的意愿行事:
function fancyFunction<T>(props: TrueProps<T> | FalseProps<T>): void {
if (props.isString === true) {
props.submit('return a string');
} else if (props.isString === false) {
props.submit(props.value);
}
}
现在在这一点上,您会注意到您的所有三个调用都fancyFunction()
给出了错误。那是因为args1
,args2
和args3
都被推断为比您想要的更宽的类型。文字true
或false
倾向于扩大类型boolean
,因为这通常是人们想要的。(对于let foo = true;
,大多数人认为foo = false;
应该允许后续)。如果您想覆盖它并保持args
变量尽可能窄(因此true
将被推断为 typetrue
而不是boolean
),那么执行此操作的一种方法(在 TS3.4+ 中)是使用const
断言:
const args1 = {
value: 2,
isString: true as const, // const assertion
submit: (arg: string) => console.log(arg),
};
fancyFunction(args1); // okay
const args2 = {
value: { id: 2 },
isString: false as const, // const assertion
submit: (arg: { id: number }) => console.log(arg),
};
fancyFunction(args2); // okay
const args3 = {
value: { id: 2 },
isString: false as const, // const assertion
submit: (arg: string) => console.log(arg),
}
fancyFunction(args3); // error!
// Types of property 'submit' are incompatible
这应该对你有用。希望有帮助;再次祝你好运!
推荐阅读
- file - 将大量少量数据写入文件(如日志记录)
- linux - 使用 auth_to_local 将登录名转换为 Kerberos 主体名称
- c# - 在 Unity C# 中重置自己后如何让计时器继续运行
- variables - docker-compose 命令中的变量替换
- matrix - 使用 malloc 的矩阵乘法,无需用户输入
- javascript - 如何测试使用 Jest 抛出的异常
- clojure - 在 Clojure 中,您可以将项目添加到倒数第二个列表中吗?
- python - 使用 Python 将文本/日期/时间添加到网络表单
- dotnetnuke - 升级到 DNN 9.2.2 时搜索结果模块“发生严重错误”
- java - EasyMock 在 final 方法上抛出不兼容的返回值类型