繁体   English   中英

TypeScript 联合类型缩小和赋值问题

[英]TypeScript union type narrowing and assignment problem

TypeScript 可以使用如下示例代码正确缩小联合类型:

interface Callable {
  call(): void
}
declare function getCallable(): Callable

let x: string | Callable = { call(){} }

if (typeof x === 'string') {
  x = getCallable()
  // `x` can only be `Callable` here
}
x.call()

但它在实际代码上不起作用,类似于上面的代码:

form(obj: object | FormData): Request {
    if (!(obj instanceof FormData)) {
        const form = new FormData()
        for (const [k, v] of Object.entries(obj)) {
            form.append(k, v)
        }
        obj = form
    }
    // `obj` must be FormData here, but why `obj` is still `object | FormData`?
    const stream = new Readable()
    stream.push(obj.getBuffer()) // FormData has getBuffer() and getHeaders()
    this._body = stream
    this.header(obj.getHeaders())
    return this
}

我认为!(obj instanceof FormData)意味着只有object可以进入if块,并且obj那里被分配给FormData ,所以obj必须是FormData 但是 TypeScript 编译器抱怨obj没有getBuffer()getHeaders() ,因为它们是object | FormData object | FormData ,而不是FormData 另外,如果不直接转换(<FormData>obj).getBuffer() ,我该怎么办?

该问题与 TS 如何处理参数有关。 它们被视为const而不是let 这意味着 TS 不遵循参数的重新分配。 当然你可以这样做,因为在运行时它是可能的(重新分配 const 不是)但 TS 处于“const 模式”的参数。 解决方案是临时变量:

function form(obj: object | FormData): Request {
    let finalObj: FormData;
    if (!(obj instanceof FormData)) {
        const form = new FormData()
        for (const [k, v] of Object.entries(obj)) {
            form.append(k, v)
        }
        finalObj = form
    } else {
      finalObj = obj;
    }
    // rest of the code should use finalObj

为什么 TS 这样做 - 通常重新分配参数不是一个好习惯,因此将它们视为const是合理的。 看看与该行为类似的问题 - 在这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM