如何在不忽略类型的情况下在打字稿中 'build an object'
How do I 'build an object' in typescript without ignoring types
嗨,我正在努力在打字稿中做一个常见的 javascript 模式,而不是使用 any
来忽略类型。我正在尝试编写一个根据某些条件构建对象的函数,并提供正确的 return 类型。我将其归结为以下示例:
是否可以在不使用 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)
return 类型对于 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 尚不能执行此操作。最好的方法是利用现有的打字方式,例如在不保证最终结果的形状的情况下检查对象中的拼写错误。
嗨,我正在努力在打字稿中做一个常见的 javascript 模式,而不是使用 any
来忽略类型。我正在尝试编写一个根据某些条件构建对象的函数,并提供正确的 return 类型。我将其归结为以下示例:
是否可以在不使用 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)
return 类型对于 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 尚不能执行此操作。最好的方法是利用现有的打字方式,例如在不保证最终结果的形状的情况下检查对象中的拼写错误。