microsoft / microsoft/TypeScript

type inference breaks with composition function using extend on generic arguments

Aperta
#44,384 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Needs Investigation
Lingua principale
Go
Stelle
111k
Fork
14.4k
Merge medio
1g 19h
PR unite (30g)
117

Descrizione

Bug Report

Type inference breaks with composition function using extend on generic arguments. I came across this issue while trying to implement composition for type guard functions see. it worked mostly but in some cases was getting strange type error demonstrated here, then I tried to change type guards with functions and the issue has persisted. Meaning that it's more general issue and not specific to type guards.

🔎 Search Terms

type guard composition extend inference

🕗 Version & Regression Information

Tested on ts@4.0-4.4 and all the versions have this issue

⏯ Playground Link

Playground link with relevant code

💻 Code
type Func<Input, Output> = (value: Input) => Output;

const flow =<I, O extends I, O2 extends O>
  (f: Func<I, O>,g: Func<O, O2>): Func<I, O2> =>
    (i: I): O2 => g(f(i))

const pipe = <I, O>
  (i: I, f: Func<I,O>): O =>
    f(i)


type ABC = AB | "C"
type AB = "A" | "B"
declare const ab: AB | undefined
declare const isB: Func<ABC,"B">
declare function notUndefined<T>(input: T | undefined): T


const b: "B" = pipe(
    ab,
    // infered type is:
    // flow<
    //   AB | undefined
    // , AB | undefined <---- here is error `udefined` shuold be removed
    // , "B">
    // ( f: Func<AB | undefined, AB | undefined>
    // , g: Func<AB | undefined, "B">
    // ): Func<...>
    flow(notUndefined, isB)
    //                 ~~~
    // because of incorectly infered type getting this error:
    //  Argument of type 'Func<ABC, "B">' is not assignable to parameter of type 'Func<AB | undefined, "B">'.
    //   Type 'AB | undefined' is not assignable to type 'ABC'.
    //     Type 'undefined' is not assignable to type 'ABC'.(2345)
    
    // if I specify type arguments it will work fine:
    // flow<AB | undefined,AB,"B">(notUndefined, isB)   
)
 


// NOTE: if we were to use notUndefined without generic argument all would be just fine:
// declare function notUndefined(input: AB | undefined): AB

// NOTE: both of this work just fine
const abnn1: AB = pipe(ab, notUndefined)
const abnn2: AB = pipe(ab, flow(notUndefined,notUndefined))

// NOTE following lines compiling proves that `isB: Func<ABC,"B">` is asignable to `isB2: Func<AB, "B">` 
declare const isB2: Func<AB, "B">
declare const acceptIsB2: (check: Func<AB, "B">) =>  void
acceptIsB2(isB)
acceptIsB2(isB2)
🙁 Actual behavior

as shown in code snippet type is inferred incorrectly and I'm getting compiler error .

🙂 Expected behavior

type should be inferred correctly.

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 eseguendo la riproduzione collegata in TypeScript Playground e confrontando flow(notUndefined, isB) con gli argomenti di tipo forniti esplicitamente. Traccia il modo in cui vengono inferiti gli argomenti generici per la funzione di composizione. Il lavoro è completo quando l'esempio inferisce il tipo intermedio senza includere undefined e compila con il risultato atteso "B".

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
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.