Typescript: Não foi possível atribuir um valor compatível a propriedade tipada genérica usando `extends` na definição genérica.

Criado em 7 abr. 2017  ·  3Comentários  ·  Fonte: microsoft/TypeScript

Versão TypeScript: 2.2.2

Posso estar entendendo mal como os genéricos funcionam (se sim, por favor me indique a direção certa), mas isso parece um bug.

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

Comportamento esperado:
Na classe Component do exemplo acima não causa erros ao usar a interface BaseState diretamente. Espero o mesmo comportamento da classe GenericComponent uma vez que State genérico estende explicitamente BaseState .

Comportamento real:
Em vez disso, recebo o seguinte erro relacionado a this.setState({ on: value > 0 }); : "Argumento do tipo '{on: boolean;}' não pode ser atribuído ao parâmetro do tipo 'Estado'."

Question

Comentários muito úteis

Considere o que acontece se você escrever isto

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 comentários

Considere o que acontece se você escrever isto

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

Aqui está um exemplo simplificado:

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

O motivo pelo qual isso não funciona é que só será válido quando Stateful for instanciado com um argumento de tipo precisamente equivalente a { on: boolean } .

Basicamente, _existe_ um tipo T , satisfazendo as restrições do argumento de tipo Stateful , de modo que a instanciação é válida, mas isso não se aplica _para todos os_ tipos T onde T satisfaz a restrição do argumento de tipo de Stateful .

Portanto, o código errôneo acima afirma que, para todos os tipos T<T> onde T, Stateful`.

Logicamente, podemos olhar para isso da seguinte maneira

Afirmação

  1. Seja P o tipo { on: boolean }
  2. Para todos os tipos T forma que T seja atribuível a P , a definição de Stateful<T> acima é válida

Rejeição por contra-exemplo

  1. Seja U o tipo { on: boolean, value: number }
  2. U ser atribuído a P -> por definição
  3. Stateful<U> é inválido -> por substituição
  4. Portanto, existe um tipo T tal que T ser atribuído a P e Stateful<T> é uma instanciação inválida -> por implicação

@RyanCavanaugh @aluanhaddad Droga, eu sabia disso. Fiquei confuso enquanto tentava resumir o problema a algo mais simples. Então, vamos tentar de novo. E neste caso, usar um Partial? Ainda recebo um erro semelhante.

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>'
    }
}
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

disshishkov picture disshishkov  ·  224Comentários

tenry92 picture tenry92  ·  146Comentários

rbuckton picture rbuckton  ·  139Comentários

RyanCavanaugh picture RyanCavanaugh  ·  205Comentários

Gaelan picture Gaelan  ·  231Comentários