异常的TypeScript行为

时间:2019-08-01 16:41:01

标签: typescript

说我有以下TypeScript代码:

type FieldArray = string[]
type FieldSet = Record<string, any>

type FieldParams =
  | [ FieldArray, FieldSet ]
  | [ FieldArray ]
  | [ FieldSet ]

function convertFieldParams (fields: FieldParams): Field[] {
  const normalised = typeof fields[1] === 'undefined'
    ? fields[0] instanceof Array
      ? [ fields[0], {} ]
      : [ [], fields[0] ]
    : fields

  // ...
}

我希望normalised变量由于类型检查而具有[ FieldArray, FieldSet ]的类型,尽管它在编辑器中显示为Record<string, any>[]

据我了解,TypeScript对可能的代码路径有所了解,因此应该能够在此处计算类型。

我是误解还是TS中的错误?

2 个答案:

答案 0 :(得分:1)

您正确理解了它,可能不是错误。

这句话是100%正确的:

  

据我了解,TypeScript对可能的代码路径有所了解,因此应该能够在此处计算类型。

此处的关键字是“ some”。 Typescript可以很好地推断类型,并且会尽力做到这一点,但这并不完美。 Typescript可以和不能自动推断的内容在每个发行版中都会增加,但我不会称其为Bug。最多这是一个尚未开发的功能。

答案 1 :(得分:0)

我要说的是,当您检查其中一个元素的内容时,通过控制流分析来缩小元组的合并范围可能是一个错误(例如,typeof fields[1] === "undefined"应该消除其中的一个分支)联盟,但没有发生)。我发现an issue报告了相同或相似的内容,但看起来好像没有人花很多时间在看它。如果您愿意的话,您可能想要解决该问题并给它一个?或提供一个新的示例来说明失败的地方。

但是,就您而言,我将更改您的测试,以利用TypeScript中的元组在编译时已知的事实fixed lengths。如果您选中fields.length === 1,则typeof fields[1] === "undefined"的缩小范围将自动发生。


这里的另一个问题是,当您创建像const arr = [1, 2, 3]这样的数组文字时,TypeScript会倾向于推断像number[]这样的数组类型而不是像[number, number, number]这样的元组类型甚至是像[1, 2, 3]这样的文字的元组。如果您需要其他推断,则需要为其提供上下文以暗示这种推断。 (您可以了解编译器用来推断较窄/较宽类型here的规则。)例如,像const arr: [number, number, number] = [1, 2, 3]这样的注释将使编译器有机会进行 check 类型,而不是推断它。如果您写const arr: [number, number, number] = [1, 2],将是一个错误。在您的情况下,如果您希望normalised的类型为[FieldArray, FieldSet],则应对此进行注释,如果您错了,编译器会警告您。


这是更改后的代码:

function convertFieldParams(fields: FieldParams): void {
  const normalised: [FieldArray, FieldSet] =
    fields.length === 1
      ? fields[0] instanceof Array
        ? [fields[0], {}]
        : [[], fields[0]]
      : fields;
}

现在可以正常运行了。希望能有所帮助;祝你好运!

Link to code