Búsqueda de sitios web

typescript - ¿Cómo definir una función genérica en una interfaz?


Encontré una respuesta para definir una función con un tipo unión:

type ValueType = number[] | string[] | number | string

type X<T extends ValueType> = (inp: T) => void;

const x: X<number> = (inp) => {
  inp // number
};

const y: X<string> = (inp) => {
  inp // string
};

Pero cuando lo uso, obtengo un error:

type ValueType = number[] | string[] | number | string

interface I1<X>{
  setValue: <X extends ValueType>(value: X) => void
}

const i1: I1<number> = {
  setValue: (value: number) => {
    console.log(value)
  }
}

Información del aviso del compilador:

TS2322: Type '(value: number) => void' is not assignable to type '<X extends ValueType>(value: X) => void'.   
Types of parameters 'value' and 'value' are incompatible.     
Type 'X' is not assignable to type 'number'.       
Type 'ValueType' is not assignable to type 'number'.         
Type 'string' is not assignable to type 'number'.  
test.ts(23, 3): The expected type comes from property 'setValue' which is declared here on type 'I1<number>'

¿Qué estoy haciendo mal? Me parece que estos dos fragmentos de código no son diferentes.

Respuesta #1

En su definición de interface I1<X>, no está utilizando el parámetro de tipo X.

Cuando defines el método setValue<X> dentro de I1<X>, no estás utilizando el tipo X existente. En cambio, estás declarando un parámetro de tipo separado para el método, que también resulta llamarse X.

Solución fácil: elimina el parámetro de tipo del método:

type ValueType = number[] | string[] | number | string

interface I1<X extends ValueType>{
  setValue: (value: X) => void
}

const i1: I1<number> = {
  /* Bonus: TS will infer the type of `value` for you here */
  setValue: (value) => {
    console.log(value)
  }
}

Enlace del parque

Respuesta #2

Haz esto:

interface I1<X extends ValueType>{
  setValue: (value: X) => void
}

En lugar de

interface I1<X>{
  setValue: <X extends ValueType>(value: X) => void
}