说我有以下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中的错误?
答案 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;
}
现在可以正常运行了。希望能有所帮助;祝你好运!