首页 > 解决方案 > 打字稿条件属性未检测到错误的功能参数

问题描述

条件类型应该允许智能属性,我已经设法从@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);

打字稿代码可以在这里找到。

标签: typescript

解决方案


与您的其他问题一样,fancyFunction()它只是通用 inT而不是Sin Props<T, S>。当您只使用Props<T>时,您会得到一个isString属性与其属性不相关的类型submit。它们都是联合体,没有什么可以阻止isStringwhilefalsesubmittype (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,args2args3都被推断为比您想要的更宽的类型。文字truefalse倾向于扩大类型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

这应该对你有用。希望有帮助;再次祝你好运!

链接到代码


推荐阅读