conditional type应该允许使用智能属性,但是在最后一行中,以下所有内容都会以某种方式失败:
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: FalseProps<T> | TrueProps<T>): void {
if (props.isString === true) {
props.submit('submit a string');
} else if (props.isString === false) {
props.submit(props.value);
}
}
const args = {
value: 2,
isString: true,
submit: (arg: string) => console.log(arg),
};
fancyFunction(args);
我得到的是:
Argument of type '{ value: number; isString: boolean; submit: (arg: string) => void; }' is not assignable to parameter of type 'Props<string, boolean>'.
Types of property 'value' are incompatible.
Type 'number' is not assignable to type 'string'.
我正在使用3.5.2版
注意:收到@jcalz回答后,我用后续问题扩展了问题,可以在这里找到:Typescript conditional property not detecting bad functional argument
答案 0 :(得分:1)
我认为这里有很多问题。
首先急切要解决您的条件类型,因为fancyFunction()
在S
中不是通用的,因此S
采用其默认值boolean
,因此{ {1}}只是类型submit
,而((arg: string) => void) | ((arg: T) => void)
根本不是条件类型。我认为可以,但是可能无法达到您期望的方式。
从Props<T>
()的呼叫签名的角度来看
fancyFunction
,function fancyFunction<T>(props: Props<T>): void;
类型是
Props<T>
您的interface Props<T> {
value: T;
isString: boolean;
submit: ((arg: string) => void) | ((arg: T) => void);
}
值被推断为类型
args
(除了:您是否期望const args: {
value: number;
isString: boolean;
submit: (arg: string) => void;
}
的类型为isString
?TypeScript在默认情况下不起作用。您可以使用const
assertion,如果需要{{1 }}进行更狭义的推断)
您正在呼叫true
。这意味着编译器需要在给定args
的情况下推断fancyFunction(args)
中的类型T
。您可以在Props<T>
中看到出现args
的两个地方。这些都是潜在的推断站点或Props<T>
。意思是,当编译器查看T
时,可能会同时查看两者 T
属性和args
属性的参数类型以尝试找出value
。
当它查看submit
方法的参数时,会看到T
,因此submit
成为string
的候选者。它尝试并且失败。 Blecch。
您可能一直假设编译器将仅使用string
来推断T
,并且value
中的类型T
应该是“ {{3} }”(也许您没有以这些特定术语考虑)。好吧,实际上TypeType中没有这些,但是non-inferential type parameter使得它往往不会被广泛地参考。在您不希望进行推断的位置,将T
更改为submit
:
T
如果我进行更改,错误就会消失:
T & {}
我想你想要的是什么。
同样,您可能希望更多地关注使用条件类型和interface Props<T> {
value: T;
isString: boolean;
submit: ((arg: string) => void) | ((arg: T & {}) => void); // change here
}
变量的类型所做的事情,只是为了确保您正在执行自己打算做的事情。但是fancyFunction(args); // okay, T inferred as number
技巧至少应该可以帮助您解决泛型类型推断的麻烦。
好的,希望能有所帮助。祝你好运!
there is an "official" way to lower the priority of an inference site