microsoft / microsoft/TypeScript

Error on function return is less useful than it should be

Aperta
#63,357 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Domain: check: Contextual Types Possible Improvement
Lingua principale
Go
Stelle
111k
Fork
14.3k
Merge medio
2g 4h
PR unite (30g)
132

Descrizione

🔍 Search Terms

"contextual typing of function return values" "function return error in the wrong place"

✅ Viability Checklist
⭐ Suggestion

Often when writing a function where the return type should be known, errors appear overly complicated and far away from their source.

type Ret = {a: number};
type Fn = () => Ret;


const issue: Fn = () => {
//    ^ it shows the error here: Type '() => { a: string; }' is not assignable to type '() => { a: number; }'.
    return {a: "25"};
//          ^ instead of here
};


// adding an explicit return type fixes it
const workaround1: Fn = (): Ret => {
    return {a: "25"};
//          ^ shows here: Type 'string' is not assignable to type 'number'.
};


// returning without a block body fixes it
const workaround2: Fn = () => ({a: "25"});
//                              ^ shows here: Type 'string' is not assignable to type 'number'.


// using a helper function fixes it
function inferRet<T>(arg: NoInfer<T>): T {
    return arg;
}
const workaround3: Fn = () => {
    return inferRet({a: "25"});
//                   ^ shows here: Type 'string' is not assignable to type 'number'.
};

Unfortunately, this would be a breaking change as it would cause some existing working code to now error, so it would have to be added under a compiler flag or wait for 7.0/8.0:

const breaking: Fn = () => {
    return {a: 25, b: 56};
//                 ^ previously, there would be no error here.
//                   with this change: Object literal may only specify known properties, and 'b' does not exist in type '{ a: number; }'.
};

Playground link

📃 Motivating Example
interface App {
    start: () => {
        title: {
            name: string,
        },
    },
}

export const app: App = {
    start: () => {
        return {
            title: {
                name: 25,
            },
        };
    },
};

Playground link

Previously, the error would show as:

10 |     start: () => {
         ~~~~~
Type '() => { title: { name: number; }; }' is not assignable to type '() => { title: { name: string; }; }'.
  Call signature return types '{ title: { name: number; }; }' and '{ title: { name: string; }; }' are incompatible.
    The types of 'title.name' are incompatible between these types.
      Type 'number' is not assignable to type 'string'.(2322)
input.tsx(2, 5): The expected type comes from property 'start' which is declared here on type 'App'

With this change, the error will show as:

13 |                name: 25,
                    ~~~~
Type 'number' is not assignable to type 'string'.(2322)
input.tsx(2, 5): The expected type comes from property 'name' which is declared here on type '{ name: string; }'

The second one is clearly easier to read and fix

💻 Use Cases
  1. What do you want to use this for?
    Interfaces that define functions with return types
  2. What shortcomings exist with current approaches?
    workaround 1: Explicitly setting the return type is annoying, and shouldn't need to be done when typescript clearly knows what it should be.
    workaround 2: Not using a block body is often not reasonable when computation needs to be done in the body of the function.
    workaround 3: You shouldn't need to define a helper function for this
  3. What workarounds are you using in the meantime?
    Every time I define a function where the return type could be inferred, I always specify it manually to make the errors easier to read.

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 i due esempi di Playground per riprodurre le diagnosi attuali e confrontare le posizioni e i messaggi segnalati. Analizza come vengono gestiti i tipi di ritorno contestuali per le funzioni con corpo a blocco, quindi verifica che gli errori vengano spostati sull'espressione di ritorno problematica senza modificare il comportamento documentato delle proprietà in eccesso.

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à
Tranquilla
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.