我有一个函数,它接受 A 中定义的类型作为参数,但我想让输入更具限制性,所以我创建了 B。
interface A {
readonly x: any;
}
interface B extends Omit<A, 'x'> {
readonly x: number;
}
问题是,这个函数不会接受 B 中的类型,即使它比 A 更严格。相反,我得到错误 No overload matches this call
,说 Type(props: B) => number is not assignable to type (props: A) => number"
。
这个函数也不接受 props: { x : number }
,给我一个类似的错误信息。
答案 0 :(得分:2)
问题在于函数参数是 contravariant。与正常值类型的可分配性相比,它们的可分配性以相反的方向检查。这就是为什么您不能将接受有限值子集的函数分配给接受更广泛值集的函数:
interface A {
readonly x: unknown;
}
interface B extends Omit<A, 'x'> {
readonly x: number;
}
declare function narrowerFn(props: B): number
const widerFn: (props: A) => number = narrowerFn // errror
这是一个完美的意义。由于目标端函数可以接受例如源端函数不知道如何处理的字符串。
但它在相反的方向上完美地工作:
interface A {
readonly x: string;
}
interface B extends Omit<A, 'x'> {
readonly x: number | string;
}
declare function widerFn(props: B): number
const narrowerFn: (props: A) => number = widerFn
现在目标端函数只能接受源端函数可以完美处理的值的子集。
答案 1 :(得分:1)
首先,您不需要Omit
。只需按如下方式覆盖该属性:
interface A {
readonly x: any;
}
interface B extends A {
readonly x: number;
}
此外,我创建了以下示例来突出问题:
type FA = (props: A) => number;
type FB = (props: B) => number;
const fb: FB = ({ x }) => x + 1;
const fa: FA = fb;
// Unsafe usage, cause fb expects numbers, not strings
console.log(fa({ x: '1' })); // Output "11" instead of 2