microsoft / microsoft/TypeScript

Strange behaviour with assignability and generics

Aperta
#36,311 1 commento 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

TypeScript Version: 3.7.2

Search Terms:

I've read through the related issues and the origin behind this error message, but I still can't wrap my head around this particular case, and it feels like a bug to me. In particular, this feels extra weird because the issue goes away if I just add an extra generic parameter on the interface - even though they are really doing the same thing.

It feels like TypeScript should be able to figure out, that if I pass e.g. Hello1<(a: number) => void> to whoops(), then it should be able to resolve C into (a: number) => void and A into [number]. And if, for some reason, the callee specifies an incompatible set of generics to the functions, that is should fail then, instead of at the function definition.

There are some variations I've tried on the exact signature of the function, but I haven't found anything that works.

Expected behavior: Both examples compile.

Actual behavior: Only one example compiles. The other fails with:

Type 'C' does not satisfy the constraint '(...args: any[]) => void'.
  Type '(...args: A) => void' is not assignable to type '(...args: any[]) => void'.
    Types of parameters 'args' and 'args' are incompatible.
      Type 'any[]' is not assignable to type 'A'.
        'any[]' is assignable to the constraint of type 'A', but 'A' could be instantiated with a different subtype of constraint 'any[]'.

Related Issues: https://github.com/microsoft/TypeScript/issues/29049

Code

// this doesn't work
interface Hello1<C extends (...args: any[]) => void> {
    _1: C
}

function whoops<A extends any[], C extends (...args: A) => void>(
    hello: Hello1<C>
) {}

// this does!
interface Hello2<A extends any[], C extends (...args: A) => void> {
    _1: A
    _2: C
}

function ok<A extends any[], C extends (...args: A) => void>(
    bye: Hello2<A, C>
) { }

Compiler Options
{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "useDefineForClassFields": false,
    "alwaysStrict": true,
    "allowUnreachableCode": false,
    "allowUnusedLabels": false,
    "downlevelIteration": false,
    "noEmitHelpers": false,
    "noLib": false,
    "noStrictGenericChecks": false,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "esModuleInterop": true,
    "preserveConstEnums": false,
    "removeComments": false,
    "skipLibCheck": false,
    "checkJs": false,
    "allowJs": false,
    "declaration": true,
    "experimentalDecorators": false,
    "emitDecoratorMetadata": false,
    "target": "ES2017",
    "module": "ESNext"
  }
}

Playground Link: Provided

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 nel playground di TypeScript 3.7.2 e confronta le dichiarazioni generiche di Hello1 e Hello2, quindi leggi l’issue correlata #29049 per comprendere il contesto dell’errore di assegnabilità. Traccia il motivo per cui il primo esempio rifiuta C mentre il secondo viene compilato; il lavoro è completato quando è stato stabilito se entrambi gli esempi debbano compilare e il comportamento risolto è coperto da un test di regressione.

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

Valutazione

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

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.