在typescript中扩展联合类型别名?
我试图在编译时将一些字符串字段限制为只有某些值。问题是这些值应该是可扩展的。 下面是一个简化的示例:在typescript中扩展联合类型别名?,typescript,Typescript,我试图在编译时将一些字符串字段限制为只有某些值。问题是这些值应该是可扩展的。 下面是一个简化的示例: type Foobar = 'FOO' | 'BAR'; interface SomeInterface<T extends Foobar> { amember: T; [key: string]: string; // this really has to stay } // let's test it const yes = { amember: 'FOO
type Foobar = 'FOO' | 'BAR';
interface SomeInterface<T extends Foobar> {
amember: T;
[key: string]: string; // this really has to stay
}
// let's test it
const yes = {
amember: 'FOO'
} as SomeInterface<'FOO'>; // compiles as expected
// const no = {
// amember: 'BAZ'
// } as SomeInterface<'BAZ'>; // Type '"BAZ"' does not satisfy the constraint 'Foobar' as expected
// so far so good
// Now the problem
abstract class SomeClass<T extends Foobar> {
private anotherMember: SomeInterface<T>;
}
type Foobarbaz = Foobar | 'BAZ';
class FinalClass extends SomeClass<Foobarbaz> { //no good anymore
}
type Foobar='FOO'|'BAR';
接口接口{
成员:T;
[key:string]:string;//这真的必须保持下去
}
//让我们测试一下
常数是={
成员:“FOO”
}作为接口;//按预期编译
//常数编号={
//amember:'BAZ'
//}作为SomeInterface;//类型“BAZ”不满足预期的约束“Foobar”
//到目前为止还不错
//现在问题来了
抽象类{
私有anotherMember:SomeInterface;
}
类型Foobarbaz=Foobar |“BAZ”;
类FinalClass扩展了一些类{//不再有用了
}
错误是
类型“Foobarbaz”不满足约束“Foobar”。类型
“BAZ”不可分配给类型“Foobar”
所以问题是:在typescript中,如何将“type”限制为只包含某些字符串,但可以用其他字符串扩展?
或者这是一个XY问题,并且有一个明显更好的解决方案
Typescript 2.3.4,但我认为如果有魔力的话,我可以升级到2.4
在typescript中,如何将“type”限制为仅包含某些字符串,但可以与其他字符串一起扩展
不知道您的X问题是什么,但您始终可以引入另一个泛型参数,并通过声明扩展该参数来限制类型。键入脚本2.3,因此默认情况下,您可以像以前一样使用带有一个参数的SomeInterface
,当您需要它来扩展其他内容时,您可以显式提供:
type Foobar = 'FOO' | 'BAR';
interface SomeInterface<T extends X, X extends string=Foobar> {
amember: T;
[key: string]: string; // this really has to stay
}
// let's test it
const yes = {
amember: 'FOO'
} as SomeInterface<'FOO'>; // compiles as expected
abstract class SomeClass<T extends X, X extends string=Foobar> {
private anotherMember: SomeInterface<T, X>;
}
type Foobarbaz = Foobar | 'BAZ';
class FinalClass extends SomeClass<Foobarbaz, Foobarbaz> {
}
我认为您使用的“可扩展”一词的含义与关键字
extends
的含义不同。如果说该类型是“可扩展的”,则表示希望能够扩展该类型以接受更多值。但是当某个扩展了一个类型时,这意味着您正在缩小该类型以接受更少的值
SomeInterface
基本上只能是以下四种类型之一:
SomeInterface
:amember
可以是'FOO'
或'BAR'
SomeInterface
:amember
只能是“FOO”
SomeInterface
:amember
只能是'BAR'
SomeInterface
:amember
不能接受任何值
我有点怀疑这是你真正想要的,但只有你能确定
另一方面,如果您想定义SomeInterface
,使T
始终可以是FOO
或BAR
,但也可能是一些其他字符串
值,那么您需要的是TypeScript不完全提供的内容,这将为T
指定一个下限。类似于SomeInterface
,它不是有效的TypeScript
但是您可能只关心amember
的类型,而不关心T
。如果希望amember
为FOO
或BAR
,但也可能是其他一些字符串
值,可以如下指定:
interface SomeInterface<T extends string = never> {
amember: Foobar | T;
[key: string]: string;
}
我回答你的问题了吗?希望对您有所帮助。要实现您需要的功能,您可以通过&
符号使用
type Foobar = 'FOO' | 'BAR';
type FoobarBaz = Foobar | & 'BAZ'; // or: 'BAZ' | & Foobar
问题中的X是这样的:基类应该只能对任何Foobar操作,而子类可能有其他值。这里有一个扩展:注释中的格式很难设置,所以我最终选择了@jcalz,这就是为什么我将它标记为正确的。您的操作也是正确的,而且对于操作员的键来说是额外的荣誉。是的,这似乎解决了问题。唯一纯粹的担忧是amember:Foobar|T代码>读起来像T可以是任何东西,而不是Foobar的后代。但那是个小调。我想你是对的,因为缺少了super
。pretier会去掉额外的&
。你能链接这个技巧的来源吗?@jayarjo有一个链接,指向交叉点类型的文档(现在已弃用)。但是我找不到任何最新的文档。
const yes = {
amember: 'FOO'
} as SomeInterface; // good, 'FOO' is a Foobar
const no = {
amember: 'BAZ'
} as SomeInterface; // bad, 'BAZ' is not a Foobar
abstract class SomeClass<T extends string> {
private anotherMember: SomeInterface<T>;
}
class FinalClass extends SomeClass<'BAZ'> {
} // fine, we've added 'BAZ'
// let's make sure we did:
type JustChecking = FinalClass['anotherMember']['amember']
// JustChecking === 'BAZ' | 'FOO' | 'BAR'
type Foobar = 'FOO' | 'BAR';
type FoobarBaz = Foobar | & 'BAZ'; // or: 'BAZ' | & Foobar