Typescript: No se puede asignar un valor compatible a la propiedad genérica con tipo utilizando "extiende" en la definición genérica.

Creado en 7 abr. 2017  ·  3Comentarios  ·  Fuente: microsoft/TypeScript

Versión de TypeScript: 2.2.2

Puede que esté malinterpretando cómo funcionan los genéricos (si es así, indíqueme la dirección correcta), pero esto parece un error.

Código

// A *self-contained* demonstration of the problem follows...

interface BaseState {
    on: boolean;
};

class Component {
    state: BaseState;

    setState(state: BaseState) {
        this.state = state;
    }

    onInput({ value }: { value: number }) {
        this.setState({ on: value > 0 });  // no error
    }
}

class GenericComponent<State extends BaseState> {
    state: State;

    setState(state: State) {
        this.state = state
    }

    onInput({ value }: { value: number }) {
        this.setState({ on: value > 0 });  // error Argument of type '{ on: boolean; }' is not assignable to parameter of type 'State'.
    }
}

Comportamiento esperado:
En la clase Component en el ejemplo anterior no causa errores cuando se usa la interfaz BaseState directamente. Espero el mismo comportamiento de la clase GenericComponent ya que el genérico State extiende explícitamente BaseState .

Comportamiento real:
En su lugar, obtengo el siguiente error relacionado con this.setState({ on: value > 0 }); : "El argumento de tipo '{on: boolean;}' no se puede asignar al parámetro de tipo 'State'".

Question

Comentario más útil

Considere lo que sucede si escribe esto

var t = new GenericComponent<{on: boolean, thing: string}>();
t.onInput({ value: 30 });
t.state.thing.substr(0); // 'thing' property should exist, but doesn't

Todos 3 comentarios

Considere lo que sucede si escribe esto

var t = new GenericComponent<{on: boolean, thing: string}>();
t.onInput({ value: 30 });
t.state.thing.substr(0); // 'thing' property should exist, but doesn't

A continuación, se muestra un ejemplo simplificado:

class Stateful<State extends { on: boolean }> {
  state: State = {
    on: true
  }; // error
}

La razón por la que esto no funciona es que solo será válido cuando Stateful se instancia con un argumento de tipo exactamente equivalente a { on: boolean } .

Básicamente, _existe_ un tipo T , que satisface las restricciones del argumento de tipo de Stateful , de modo que la instanciación es válida pero esto no es válido para todos_ los tipos T donde T satisface la restricción del argumento de tipo de Stateful .

Entonces, el código errante anterior afirma que, para todos los tipos T<T> donde T, Stateful".

Lógicamente, podemos mirarlo de la siguiente manera

Afirmación

  1. Sea P el tipo { on: boolean }
  2. Para todos los tipos T manera que T se pueda asignar a P , la definición de Stateful<T> anterior es válida

Refutar con contraejemplo

  1. Sea U el tipo { on: boolean, value: number }
  2. U se puede asignar a P -> por definición
  3. Stateful<U> no es válido -> por sustitución
  4. Por lo tanto, existe un tipo T tal que T se puede asignar a P y Stateful<T> es una instanciación no válida -> por implicación

@RyanCavanaugh @aluanhaddad Shoot, lo sabía. Simplemente me confundí mientras trataba de resumir el problema en algo más simple. Así que intentemos eso de nuevo. ¿Qué pasa en este caso con el uso de un parcial? Sigo recibiendo un error similar.

interface BaseState {
    on: boolean;
};

class Component {
    state: BaseState;

    setState(partialState: Partial<BaseState>) {
        this.state = { ...this.state, ...partialState };
    }

    onInput({ value }: { value: number }) {
        this.setState({ on: value > 0 });  // no error
    }
}

class GenericComponent<State extends BaseState> {
    state: State;

    setState(partialState: Partial<State>) {
        this.state = { ...this.state, ...partialState };
    }

    onInput({ value }: { value: number }) {
        this.setState({ on: value > 0 });  // error: Argument of type '{ on: boolean; }' is not assignable to parameter of type 'Partial<State>'
    }
}
¿Fue útil esta página
0 / 5 - 0 calificaciones