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
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12829,7 +12829,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const baseTypes = getBaseTypes(source);
if (baseTypes.length) {
if (source.symbol && members === getMembersOfSymbol(source.symbol)) {
members = createSymbolTable(source.declaredProperties);
members = createSymbolTable(members.values(), SymbolFlags.TypeParameter);
}
setStructuredTypeMembers(type, members, callSignatures, constructSignatures, indexInfos);
const thisArgument = lastOrUndefined(typeArguments);
Expand Down
10 changes: 8 additions & 2 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -594,11 +594,17 @@ export function getDeclarationsOfKind<T extends Declaration>(symbol: Symbol, kin
}

/** @internal */
export function createSymbolTable(symbols?: readonly Symbol[]): SymbolTable {
export function createSymbolTable(symbols: Iterable<Symbol>, excludes?: SymbolFlags): SymbolTable;
/** @internal */
export function createSymbolTable(symbols?: Iterable<Symbol>): SymbolTable;
/** @internal */
export function createSymbolTable(symbols?: Iterable<Symbol>, excludes: SymbolFlags = 0): SymbolTable {
const result = new Map<__String, Symbol>();
if (symbols) {
for (const symbol of symbols) {
result.set(symbol.escapedName, symbol);
if (!(symbol.flags & excludes)) {
result.set(symbol.escapedName, symbol);
}
}
}
return result;
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");