microsoft / microsoft/TypeScript

Mixin expected argument type resolves to never when constrained to constructor of type whose property is typed via a type parameter

Aperta
#34,979 0 commenti 1 reazione 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

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

Descrizione

TypeScript Version: 3.8.0-dev.20191105

Search Terms: mixin 3.7 type

Code

import * as ts from "typescript";

type Constructor<T> = new (...args: any[]) => T;

export class Node<NodeType extends ts.Node = ts.Node> {
    compilerNode!: NodeType;
}

// BindingNamedNode
export interface BindingNamedNode {
    getName(): string;
}

export function BindingNamedNode<
    TCompilerNode extends ts.Node & { name: ts.BindingName; },
    TBase extends Constructor<Node<TCompilerNode>>
>(
    Base: TBase
): Constructor<BindingNamedNode> & TBase {
    return {} as any;
}

// InitializerableNode
export interface InitializerableNode {
    removeInitializer(): this;
}

export function InitializerableNode<
    TCompilerNode extends ts.Node & { initializer?: ts.Expression; },
    TBase extends Constructor<Node<TCompilerNode>>
>(
    Base: TBase
): Constructor<InitializerableNode> & TBase {
    return {} as any;
}

// BindingElement
export class BindingElement extends InitializerableNode(BindingNamedNode(Node))<ts.BindingElement> {
}

Other Code

Or my original code... I think it's more correct to do the above, but should either of these error?

import * as ts from "typescript";

type Constructor<T> = new (...args: any[]) => T;

export class Node<NodeType extends ts.Node = ts.Node> {
    compilerNode!: NodeType;
}

// BindingNamedNode
export type BindingNamedNodeExtensionType = Node<ts.Node & { name: ts.BindingName; }>;

export interface BindingNamedNode {
    getName(): string;
}

export function BindingNamedNode<T extends Constructor<BindingNamedNodeExtensionType>>(
    Base: T
): Constructor<BindingNamedNode> & T {
    return {} as any;
}

// InitializerableNode
export type InitializerableNodeExtensionType = Node<ts.Node & { initializer?: ts.Expression; }>;

export interface InitializerableNode {
    removeInitializer(): this;
}

export function InitializerableNode<T extends Constructor<InitializerableNodeExtensionType>>(
    Base: T
): Constructor<InitializerableNode> & T {
    return {} as any;
}

// BindingElement
export class BindingElement extends InitializerableNode(BindingNamedNode(Node))<ts.BindingElement> {
}

Expected behavior: No errors, as in TS < 3.7

TS 3.6.3 Playground

Actual behavior:

TS2345: Argument of type 'typeof Node' is not assignable to parameter of type 'never'.

export class BindingElement extends InitializerableNode(BindingNamedNode(Node))<ts.BindingElement> {
                                                                         ~~~~
}

Playground Link: TS 3.8.0-dev.20191105 Playground

Other Comments

The issue does not occur when the type parameter is inlined (Playground).

Also, I wouldn't be surprised if I was doing something wrong here, but this has worked in the past.

Workaround

Pass the class constructor into a function typed like so and the compile error goes away (Playground):

const createBase = <T extends typeof Node>(ctor: T) => InitializerableNode(BindingNamedNode(ctor));
export class BindingElement extends createBase(Node)<ts.BindingElement> {
}

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 riproducendo l’esempio di constructor-mixin segnalato nel playground di TypeScript 3.8.0-dev e confrontalo con il playground di TypeScript 3.6.3. Analizza perché l’argomento del costruttore viene risolto in never quando il tipo della proprietà utilizza un parametro di tipo; il lavoro è completato quando l’esempio segnalato viene compilato senza errori preservando i vincoli generici.

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.