![](/img/trans.png)
[英]Conditional Generic Types in TypeScript use Discriminated Union
[英]How to use generic type and union types in typescript
我有一个 class,当我初始化它时,我传入一个值,或者一个关于该值的 object
例如
new Field<string>('test')
new Field<string>({value: 'test', inactive: 'preview'})
但state.value
是错误的。 (“FieldState”类型上不存在属性“值”。类型“T”上不存在属性“值”.ts(2339))
interface BoxedValue<T> {
value: T
inactive: 'disabled'| 'preview'| 'hidden'
}
type FieldState<T> = BoxedValue<T> | T
class Field<T> {
value: T
_pendingValue: T
constructor(state: FieldState<T>) {
if(typeof state === 'object') {
this.value = this._pendingValue = state.value
} else {
this.value = this._pendingValue = state
}
}
}
谢谢你的解决方案,我修改了代码,但我现在有一个新问题。
class Field<T> {
value: T
_pendingValue: T
constructor(state: FieldState<T>) {
if(this._isBoxedValue(state)) {
this.value = this._pendingValue = state.value // Property 'value' does not exist on type 'FieldState<T>'.Property 'value' does not exist on type 'T'.
} else {
this.value = this._pendingValue = state
// Type 'FieldState<T>' is not assignable to type 'T'.
// T' could be instantiated with an arbitrary type which could be unrelated to 'FieldState<T>'.
// Type 'BoxedValue<T>' is not assignable to type 'T'.
// 'T' could be instantiated with an arbitrary type which could be unrelated to 'BoxedValue<T>'
}
}
_isBoxedValue(state: FieldState<T>): boolean{
return typeof state === 'object' && state !== null &&
Object.keys(state).length === 2 && 'value' in state && 'inactive' in state;
}
}
为什么我把判断条件放在isboxedvalue function里面会出错,而在构造函数里面却没有?
嗨,问题是没有任何事情不会发生在每个人身上。 您的typeof state === "object"
是对 BoxedValue 的测试,但有一个小错误:T 也可以是 object。
interface BoxedValue<T> {
value: T;
inactive: 'disabled' | 'preview' | 'hidden';
}
type FieldState<T> = BoxedValue<T> | T;
class Field<T> {
value: T;
_pendingValue: T;
constructor(state: FieldState<T>) {
if (typeof state === 'object' && "value" in state) {
this.value = this._pendingValue = state.value;
} else {
this.value = this._pendingValue = state;
}
}
}
interface BoxedValue<T> {
value: T;
inactive: 'disabled' | 'preview' | 'hidden';
}
type FieldState<T> = BoxedValue<T> | T;
class Field<T extends (string | number /* or your type */)> {
value: T;
_pendingValue: T;
constructor(state: FieldState<T>) {
if (typeof state === 'object') {
this.value = this._pendingValue = state.value;
} else {
this.value = this._pendingValue = state;
}
}
}
您应该使用in运算符。 Using typeof state ==='object'
can only guarantee that state
is of object
type(if the value of state
is null
, it's a object
type as well), but cannot guarantee that it has a value
property.
in 运算符还充当类型的缩小表达式。
interface BoxedValue<T> {
value: T
inactive: 'disabled'| 'preview'| 'hidden'
}
type FieldState<T> = BoxedValue<T> | T
class Field<T> {
value: T
_pendingValue: T
constructor(state: FieldState<T>) {
if('value' in state) {
this.value = this._pendingValue = state.value
} else {
this.value = this._pendingValue = state
}
}
}
更新:
您应该为_isBoxedValue
方法使用用户定义的类型保护。 返回类型state is BoxedValue<T>
是类型谓词,而不是boolean
。
例如
interface BoxedValue<T> {
value: T
inactive: 'disabled'| 'preview'| 'hidden'
}
type FieldState<T> = BoxedValue<T> | T
class Field<T> {
value: T
_pendingValue: T
constructor(state: FieldState<T>) {
if(this._isBoxedValue(state)) {
this.value = this._pendingValue = state.value;
} else {
this.value = this._pendingValue = state;
}
}
_isBoxedValue(state: FieldState<T>): state is BoxedValue<T>{
return typeof state === 'object' && state !== null &&
Object.keys(state).length === 2 && 'value' in state && 'inactive' in state;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.