【发布时间】: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 两次,它不会在意。
这是我的尝试:
// 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