microsoft / microsoft/TypeScript

Improve Type guards to correctly work with for-of loops

Aperta
#29,283 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Suggestion
Lingua principale
Go
Stelle
111k
Fork
14.3k
Merge medio
2g 4h
PR unite (30g)
132

Descrizione

Search Terms

for-of, Type Guard

Suggestion

At the moment a paradigm of call-Parameter-Testing I apply works well in case of one parameter, but if I want to shorten the testing of multiple parameters using a for-of loop the type assertion fails.

Use Cases

Correct type guarding of multiple parameters which are supposed to be the same type but to be handled differently

Examples

type generalObj<T> = {
    value: T,
};

type numObj = generalObj<number>

const isNumObj = (testObj: generalObj<any>): testObj is numObj => {
    //some logic here...
    return true;
}

const numConsumer = (param: numObj) => param;

const shouldWork = (shouldBeNumObj: generalObj<number | string>) => {
    for (const c of [shouldBeNumObj]) {
        if (!isNumObj(c)) {
            return console.error('no numObj')
        }
    }
    // error here despite the right type ensured
    numConsumer(shouldBeNumObj);
}

const doesWork = (shouldBeNumObj: generalObj<number | string>) => {
    if (!isNumObj(shouldBeNumObj)) {
        return console.error('no numObj')
    }
    numConsumer(shouldBeNumObj);
}

const shouldWork2 = (shouldBeNumObj: Array<generalObj<number | string>>) => {
    for (const c of shouldBeNumObj) {
        if (!isNumObj(c)) {
            return console.error('no numObj')
        }
    }
    numConsumer(shouldBeNumObj[0]);
}

const baseTypeNumConsumer = (param: number) => param; 
// curtesy of @nmain
const shouldWork3 = (shouldBeNum: string | number) => {
    for (const v of [shouldBeNum]) {
        if (typeof v !== "number") {
            return;
        }
    }
    baseTypeNumConsumer(shouldBeNum); // compiler error, but should be valid
}

const stringConsumer = (param: generalObj<string>) => param;

const couldBreakCode = (anyObjS: Array<generalObj<any>>) => {
    for (const c of anyObjS) {
        if (!isNumObj(c)) {
            return console.error('no numObj')
        }
    }
    stringConsumer(anyObjS[0])
}

const becauseThisFails = (anyObj: generalObj<any>) => {
    if (!isNumObj(anyObj)) {
        return console.error('no numObj')
    }
    stringConsumer(anyObj);
}

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
    • Could break compilation of already error-prone code where Type testing was disabled with any
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

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

Non vengono indicati file sorgente o test. Inizia riproducendo gli esempi TypeScript nell’issue e tracciando il modo in cui il narrowing del flusso di controllo gestisce le variabili testate tramite un ciclo for-of. Il lavoro è completato quando i casi validi di narrowing compilano, mentre il caso mostrato basato su any non diventa unsound.

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

Valutazione

Stack tecnologico
typescript
Ambito
compilers
Tipo di issue
Funzionalità
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
30/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.