【问题标题】:How do I 'build an object' in typescript without ignoring types如何在打字稿中“构建对象”而不忽略类型
【发布时间】:2021-03-20 01:49:46
【问题描述】:

您好,我正在努力在 typescript 中创建一个常见的 javascript 模式,而不是求助于使用 any 来忽略这些类型。我正在尝试编写一个根据某些条件构建对象的函数,并给出正确的返回类型。我将其归结为以下示例:

不使用any是否可以让下面的函数工作?

function hasAB<A extends boolean, B extends boolean>(shouldHaveA: A, shouldHaveB: B): HasAB<A, B> {
    const obj: any = {}
    if (shouldHaveA) obj.a = ""
    if (shouldHaveB) obj.b = ""
    return obj
}
type HasAB<A extends boolean, B extends boolean> = 
    (A extends true ? {a: string} : {}) &
    (B extends true ? {b: string} : {}) 

const a = hasAB(true, false)
const b = hasAB(false, true)
const ab = hasAB(true, true)

a、b 和 ab 的返回类型是正确的,但是编译器不会检查代码。你可以设置obj.a 两次,它不会在意。

See code in the playground

这是我的尝试:

// attempt 1 and 2 fails because inference takes the union of conditionals e.g.
const five = true ? 5 : 4; // five: 5 | 4
function attempt1<A extends boolean, B extends boolean>(shouldHaveA: A, shouldHaveB: B): HasAB<A, B> {
    return {
        ...(shouldHaveA ? { a: "" } : {}),
        ...(shouldHaveB ? { b: "" } : {})
    }
}
function attempt2<A extends boolean, B extends boolean>(shouldHaveA: A, shouldHaveB: B): HasAB<A, B> {
    const obj1 = shouldHaveA ? {a: ""} : {}
    const obj2 = shouldHaveB ? {...obj1, b: ""} : obj1
    return obj2;
}

// attempt 3 can't get over the hurdle of needing to assign an intial type
function attempt3<A extends boolean, B extends boolean>(shouldHaveA: A, shouldHaveB: B): HasAB<A, B> {
    let obj = {}
    if (shouldHaveA) {
        obj = { ...obj, a: "" }
    }
    if (shouldHaveB) {
        obj = { ...obj, b: "" }
    }
    return obj
}
// attempt 4 fails too
function attempt4<A extends boolean, B extends boolean>(shouldHaveA: A, shouldHaveB: B): HasAB<A, B> {
    if (shouldHaveA) {
        const a = {a: ""}
    }
    if (shouldHaveB) {
        const b = {...(a || {}), b: ""}
    }
    const final = b || {}
    return final
}
// attempt 5 fails because ternary always assumes a union
function hasAB<A extends boolean, B extends boolean>(shouldHaveA: A, shouldHaveB: B): HasAB<A, B> {
    const obj = {}
    const withA: A extends true ? {a: string} : typeof obj = shouldHaveA ? {a: ""} : obj
    const withB: withA & (B extends true ? {a: string} : {}) = shouldHaveB ? {...withA, b: ""} : withA
    return withB
}

【问题讨论】:

    标签: typescript generics type-inference


    【解决方案1】:

    TypeScript 还不能做到这一点。最好的方法是利用现有的打字方式,例如在不保证最终结果的形状的情况下检查对象中的拼写错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-16
      • 1970-01-01
      • 2019-09-07
      • 1970-01-01
      • 1970-01-01
      • 2017-12-14
      • 2021-03-17
      • 2019-09-06
      相关资源
      最近更新 更多