typescript - 在 Typescript 中,如何确保变量匹配联合类型的情况而不重写其定义?
问题描述
我有一个这样的联合类型:
type Union
= { kind: UnionKind.One, x: string }
| { kind: UnionKind.Two, y: number }
enum UnionKind { One, Two }
我想创建一个返回第一种情况的构造函数。
function one(x: string): ReturnType {
return { kind: UnionKind.One, x: x }
}
我可以指定ReturnType
为 (1){ kind: UnionKind.One, x: string }
或 (2) Union
。
(1) 有一个缺点,如果我将来更改类型,该函数仍然会成功编译:
type Union
= { kind: UnionKind.One, somethingElse: string }
| { kind: UnionKind.Two, y: number }
// unfortunately, compiles :(
function one(x: string): { kind: UnionKind.One, x: string } {
return { kind: UnionKind.One, x: x }
}
(2) 的缺点是它会丢失我确定的信息并通过,即使我返回UnionKind.Two
.
function one(x: string): Union {
return { kind: UnionKind.One, x: x }
}
const foo = one("foo"); // foo is Union although I'm sure it's of UnionKind.One
console.log(foo.x); // compilation error!
// passes although I want to return it something of `one`
function one(x: string): Union {
return { kind: UnionKind.Two, y: x.toString() }
}
好像我想说:
function one(x: string): returns conforms both to { kind: UnionKind.One, x: string } and Union {
return { kind: UnionKind.One, x: x }
}
那么,怎么说呢?另外,如果我不必重复案例的类型定义会很好。
注意:我并没有以特殊的方式使用构造函数这个词,我的意思是它是一个通用函数。
解决方案
使用{ kind: UnionKind.One } & Union
. 优点:
// (1) You don't have to write the whole definition of the case
function one(x: string): { kind: UnionKind.One } & Union {
return { kind: UnionKind.One, x: x }
}
// (2) It infers it's of the first case
const foo = one("foo");
console.log(foo.x); // Works! :)
// (3) If you return something not of `One`, it'll tell:
// happily doesn't compile :-)
function one(x: string): { kind: UnionKind.One } & Union {
return { kind: UnionKind.Two, y: x.toString() }
}
// (4) If you change the union type in the future, you'll get a compilation error :)
type Union
= { kind: UnionKind.One, somethingElse: string }
| { kind: UnionKind.Two, y: number }
// Error! :)
function one(x: string): { kind: UnionKind.One } & Union {
return { kind: UnionKind.One, x: x }
}
再次注意:您不需要重复案例的整个定义!