microsoft / microsoft/TypeScript

Computed property key names should not be widened

Aperta
#13,948 34 commenti 134 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Bug Domain: Index Types
Lingua principale
Go
Stelle
111k
Fork
14.3k
Merge medio
1g 19h
PR unite (30g)
117

Descrizione

TypeScript Version: 2.1.5

Code
The latest @types/react (v15.0.6) use Pick<S,K> to correctly type the setState method of React.Components. While this makes it now possible to merge the state of a component instead of replacing it, it also makes it harder to write a dynamic update function that uses computed properties.

import * as React from 'react';

interface Person {
  name: string;
  age: number|undefined;
}

export default class PersonComponent extends React.Component<void, Person> {
  constructor(props:any) {
    super(props);

    this.state = { 
      name: '',
      age: undefined
    };
    this.handleUpdate = this.handleUpdate.bind(this);
  }

  handleUpdate (e:React.SyntheticEvent<HTMLInputElement>) {
    const key = e.currentTarget.name as keyof Person;
    const value = e.currentTarget.value;
    this.setState({ [key]: value }); // <-- Error
  }

  render() {
    return (
      <form>
        <input type="text" name="name" value={this.state.name} onChange={this.handleUpdate} />
        <input type="text" name="age" value={this.state.age} onChange={this.handleUpdate} />
      </form>
    );
  }
}

The above should show an actual use case of the issue, but it can be reduced to:

const key = 'name';
const value = 'Bob';
const o:Pick<Person, 'name'|'age'> = { [key]: value };

which will result in the same error. Link to the TS playground

Expected behavior:
No error, because key is a keyof Person, which will result in the literal type "name" | "age". Both values that are valid keys forstate.

Actual behavior:
The compiler will throw the following error:

[ts] Argument of type '{ [x: string]: string; }' is not assignable 
     to parameter of type 'Pick<Person, "name" | "age">'.
       Property 'name' is missing in type '{ [x: string]: string; }'.

My uninformed guess is that the constant key is (incorrectly) widened to string.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia con la riproduzione ridotta nell’issue o nel TypeScript playground collegato, quindi traccia come vengono inferiti e ampliati i computed property names. Confronta il risultato con il comportamento atteso di keyof Person e con l’esempio di React setState. Il lavoro è completato quando entrambe le riproduzioni superano il controllo dei tipi senza perdere l’unione di chiavi literal.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
typescript
Ambito
compilers
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.