How to use generic type and union types in typescript

杨帝武

I have a class, and when I initialize it, I pass in a value, or an object about the value

for example

new Field<string>('test')
new Field<string>({value: 'test', inactive: 'preview'})

but state.value is error. (Property 'value' does not exist on type 'FieldState'. Property 'value' does not exist on type '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
    }
  }
}

thank your solution,I amend the code, but I have a new problem Now.

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;
  }
}

Why do I make a mistake when I put the judgment condition in the isboxedvalue function, but not in the constructor?

slideshowp2

You should use in operator. 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.

The in operator also acts as a narrowing expression for types.

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
    }
  }
}

Updated:

You should use User-Defined Type Guards for _isBoxedValue method. The return type state is BoxedValue<T> is a type predicate, NOT boolean.

E.g.

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;
  }
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Could typescript narrow union type in generic type?

How do I type a recursive function receiving an array of generic union types? (typescript)

How to fix typescript "Property does not exist on type" with union types?

Typescript generic union type

Typescript union type generic parameter

Typescript - Union Type and generic types throw incompatibility error

How to type an object with generic keys of different types in typescript

Typescript/Angular 10: component with generic union type

How to narrow down union of generic types in Typescript?

How can create a generic type that is a combination of other types in TypeScript?

How to write a TypeScript type utility that narrows union types in an object?

How to use an instance with type of union of interfaces in TypeScript?

How to filter a list of types by a generic type in TypeScript?

Use Mixins with union types in Typescript

How to use Union Type as Contraint in Generaic type parameter in TypeScript

Typescript two layer union type infer in generic

How can a TypeScript forEach, infer the types of a union, and change the return type

Type narrowing with generic union types

How to use TypeScript union types in react

In TypeScript, how to convert all types within a Union to an array of that type

TypeScript generic with conditional evaluates union types separately

Typescript union types to keys on other union type

How to use generic type for interface - TypeScript?

How to use typescript generic type as an object key

How to use the Generic Type of a Types Property?

Typescript: infer generic types in generic type constraint

Typescript: discriminate generic union in conditional type

Specify exclusive joining of union types in a Typescript generic type

How to define two fields of two generic types with the same type in typescript?