Skip to content

Transfer all declared symbols onto the type from the interface that extends another #55252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
9 changes: 8 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12829,7 +12829,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const baseTypes = getBaseTypes(source);
if (baseTypes.length) {
if (source.symbol && members === getMembersOfSymbol(source.symbol)) {
members = createSymbolTable(source.declaredProperties);
const symbolTable = createSymbolTable();
// copy all symbols (except type parameters), including the ones with internal names like `InternalSymbolName.Index`
for (const symbol of members.values()) {
if (!(symbol.flags & SymbolFlags.TypeParameter)) {
symbolTable.set(symbol.escapedName, symbol);
}
}
members = symbolTable;
}
setStructuredTypeMembers(type, members, callSignatures, constructSignatures, indexInfos);
const thisArgument = lastOrUndefined(typeArguments);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//// [tests/cases/compiler/classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts] ////

=== classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts ===
interface IObserver {
>IObserver : Symbol(IObserver, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 0, 0))

handleChange<T, TChange>(observable: IObservable<T, TChange>, change: TChange): void;
>handleChange : Symbol(IObserver.handleChange, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 0, 21))
>T : Symbol(T, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 1, 14))
>TChange : Symbol(TChange, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 1, 16))
>observable : Symbol(observable, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 1, 26))
>IObservable : Symbol(IObservable, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 2, 1))
>T : Symbol(T, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 1, 14))
>TChange : Symbol(TChange, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 1, 16))
>change : Symbol(change, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 1, 62))
>TChange : Symbol(TChange, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 1, 16))
}

interface IObservable<T, TChange = unknown> {
>IObservable : Symbol(IObservable, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 2, 1))
>T : Symbol(T, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 4, 22))
>TChange : Symbol(TChange, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 4, 24), Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 5, 10))

get(): T;
>get : Symbol(IObservable.get, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 4, 45))
>T : Symbol(T, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 4, 22))

readonly TChange: TChange;
>TChange : Symbol(TChange, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 4, 24), Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 5, 10))
>TChange : Symbol(TChange, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 4, 24), Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 5, 10))
}

export interface IReader {
>IReader : Symbol(IReader, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 7, 1))

readObservable<T>(observable: IObservable<T, any>): T;
>readObservable : Symbol(IReader.readObservable, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 9, 26))
>T : Symbol(T, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 10, 16))
>observable : Symbol(observable, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 10, 19))
>IObservable : Symbol(IObservable, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 2, 1))
>T : Symbol(T, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 10, 16))
>T : Symbol(T, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 10, 16))
}

export abstract class ConvenientObservable<T, TChange> implements IObservable<T, TChange> {
>ConvenientObservable : Symbol(ConvenientObservable, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 11, 1))
>T : Symbol(T, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 13, 43))
>TChange : Symbol(TChange, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 13, 45), Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 13, 91))
>IObservable : Symbol(IObservable, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 2, 1))
>T : Symbol(T, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 13, 43))
>TChange : Symbol(TChange, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 13, 45), Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 13, 91))

get TChange(): TChange { return null!; }
>TChange : Symbol(TChange, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 13, 45), Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 13, 91))
>TChange : Symbol(TChange, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 13, 45), Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 13, 91))

public abstract get(): T;
>get : Symbol(ConvenientObservable.get, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 14, 41))
>T : Symbol(T, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 13, 43))
}

export abstract class BaseObservable<T, TChange = void> extends ConvenientObservable<T, TChange> {
>BaseObservable : Symbol(BaseObservable, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 16, 1))
>T : Symbol(T, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 18, 37))
>TChange : Symbol(TChange, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 18, 39))
>ConvenientObservable : Symbol(ConvenientObservable, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 11, 1))
>T : Symbol(T, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 18, 37))
>TChange : Symbol(TChange, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 18, 39))

protected readonly observers = new Set<IObserver>();
>observers : Symbol(BaseObservable.observers, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 18, 98))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>IObserver : Symbol(IObserver, Decl(classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts, 0, 0))
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//// [tests/cases/compiler/classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts] ////

=== classExtendingAbstractClassWithMemberCalledTheSameAsItsOwnTypeParam.ts ===
interface IObserver {
handleChange<T, TChange>(observable: IObservable<T, TChange>, change: TChange): void;
>handleChange : <T, TChange>(observable: IObservable<T, TChange>, change: TChange) => void
>observable : IObservable<T, TChange>
>change : TChange
}

interface IObservable<T, TChange = unknown> {
get(): T;
>get : () => T

readonly TChange: TChange;
>TChange : TChange
}

export interface IReader {
readObservable<T>(observable: IObservable<T, any>): T;
>readObservable : <T>(observable: IObservable<T, any>) => T
>observable : IObservable<T, any>
}

export abstract class ConvenientObservable<T, TChange> implements IObservable<T, TChange> {
>ConvenientObservable : ConvenientObservable<T, TChange>

get TChange(): TChange { return null!; }
>TChange : TChange
>null! : never

public abstract get(): T;
>get : () => T
}

export abstract class BaseObservable<T, TChange = void> extends ConvenientObservable<T, TChange> {
>BaseObservable : BaseObservable<T, TChange>
>ConvenientObservable : ConvenientObservable<T, TChange>

protected readonly observers = new Set<IObserver>();
>observers : Set<IObserver>
>new Set<IObserver>() : Set<IObserver>
>Set : SetConstructor
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// @strict: true
// @lib: esnext
// @noEmit: true

interface IObserver {
handleChange<T, TChange>(observable: IObservable<T, TChange>, change: TChange): void;
}

interface IObservable<T, TChange = unknown> {
get(): T;
readonly TChange: TChange;
}

export interface IReader {
readObservable<T>(observable: IObservable<T, any>): T;
}

export abstract class ConvenientObservable<T, TChange> implements IObservable<T, TChange> {
get TChange(): TChange { return null!; }
public abstract get(): T;
}

export abstract class BaseObservable<T, TChange = void> extends ConvenientObservable<T, TChange> {
protected readonly observers = new Set<IObserver>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/// <reference path="fourslash.ts" />

// https://github.com/microsoft/TypeScript/issues/55251

//// interface P {}
//// interface B extends P {
//// [k: string]: number;
//// }
//// declare const b: B;
//// b.t/*1*/est = 10;

verify.quickInfoAt("1", "(index) B[string]: number");