Typescript条件属性无法用于函数自变量

时间:2019-06-19 16:12:49

标签: typescript

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

1 个答案:

答案 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