Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
32 changes: 28 additions & 4 deletions internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -21351,20 +21351,44 @@ func (c *Checker) getDefaultOrUnknownFromTypeParameter(t *Type) *Type {
return core.IfElse(result != nil, result, c.unknownType)
}

func (c *Checker) getNamedMembers(members ast.SymbolTable) []*ast.Symbol {
func (c *Checker) getNamedMembers(members ast.SymbolTable, container *ast.Symbol) []*ast.Symbol {
if len(members) == 0 {
return nil
}
// For classes and interfaces, we store explicitly declared members ahead of inherited members. This ensures we process
// explicitly declared members first in type relations, which is beneficial because explicitly declared members are more
// likely to contain discriminating differences. See for example https://github.com/microsoft/typescript-go/issues/1968.
result := make([]*ast.Symbol, 0, len(members))
var containedCount int
if container != nil && container.Flags&(ast.SymbolFlagsClass|ast.SymbolFlagsInterface) != 0 {
for id, symbol := range members {
if c.isNamedMember(symbol, id) && c.isDeclarationContainedBy(symbol, container) {
result = append(result, symbol)
}
}
containedCount = len(result)
}
for id, symbol := range members {
if c.isNamedMember(symbol, id) {
if c.isNamedMember(symbol, id) && (container == nil || container.Flags&(ast.SymbolFlagsClass|ast.SymbolFlagsInterface) == 0 || !c.isDeclarationContainedBy(symbol, container)) {
result = append(result, symbol)
}
}
c.sortSymbols(result)
c.sortSymbols(result[:containedCount])
c.sortSymbols(result[containedCount:])
return result
}

func (c *Checker) isDeclarationContainedBy(symbol *ast.Symbol, container *ast.Symbol) bool {
if declaration := symbol.ValueDeclaration; declaration != nil {
for _, d := range container.Declarations {
if declaration.Loc.ContainedBy(d.Loc) {
return true
}
}
}
return false
}

func (c *Checker) isNamedMember(symbol *ast.Symbol, id string) bool {
return !isReservedMemberName(id) && c.symbolIsValue(symbol)
}
Expand Down Expand Up @@ -24338,7 +24362,7 @@ func (c *Checker) setStructuredTypeMembers(t *Type, members ast.SymbolTable, cal
t.objectFlags |= ObjectFlagsMembersResolved
data := t.AsStructuredType()
data.members = members
data.properties = c.getNamedMembers(members)
data.properties = c.getNamedMembers(members, t.symbol)
if len(callSignatures) != 0 {
if len(constructSignatures) != 0 {
data.signatures = core.Concatenate(callSignatures, constructSignatures)
Expand Down
2 changes: 1 addition & 1 deletion internal/checker/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ func (c *Checker) getAugmentedPropertiesOfType(t *Type) []*ast.Symbol {
}
}
}
return c.getNamedMembers(propsByName)
return c.getNamedMembers(propsByName, nil)
}

func (c *Checker) TryGetMemberInModuleExportsAndProperties(memberName string, moduleSymbol *ast.Symbol) *ast.Symbol {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//// [tests/cases/compiler/explicitMembersBeforeInherited.ts] ////

=== explicitMembersBeforeInherited.ts ===
// https://github.com/microsoft/typescript-go/issues/1968

type IndentationTree<L> = TopNode<L> | VirtualNode<L> | LineNode<L> | BlankNode<L>;
>IndentationTree : Symbol(IndentationTree, Decl(explicitMembersBeforeInherited.ts, 0, 0))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 2, 21))
>TopNode : Symbol(TopNode, Decl(explicitMembersBeforeInherited.ts, 11, 1))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 2, 21))
>VirtualNode : Symbol(VirtualNode, Decl(explicitMembersBeforeInherited.ts, 7, 1))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 2, 21))
>LineNode : Symbol(LineNode, Decl(explicitMembersBeforeInherited.ts, 15, 1))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 2, 21))
>BlankNode : Symbol(BlankNode, Decl(explicitMembersBeforeInherited.ts, 19, 1))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 2, 21))

type IndentationSubTree<L> = Exclude<IndentationTree<L>, TopNode<L>>;
>IndentationSubTree : Symbol(IndentationSubTree, Decl(explicitMembersBeforeInherited.ts, 2, 83))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 3, 24))
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
>IndentationTree : Symbol(IndentationTree, Decl(explicitMembersBeforeInherited.ts, 0, 0))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 3, 24))
>TopNode : Symbol(TopNode, Decl(explicitMembersBeforeInherited.ts, 11, 1))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 3, 24))

interface NodeBase<L> {
>NodeBase : Symbol(NodeBase, Decl(explicitMembersBeforeInherited.ts, 3, 69))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 5, 19))

subs: IndentationSubTree<L>[];
>subs : Symbol(NodeBase.subs, Decl(explicitMembersBeforeInherited.ts, 5, 23))
>IndentationSubTree : Symbol(IndentationSubTree, Decl(explicitMembersBeforeInherited.ts, 2, 83))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 5, 19))
}

interface VirtualNode<L> extends NodeBase<L> {
>VirtualNode : Symbol(VirtualNode, Decl(explicitMembersBeforeInherited.ts, 7, 1))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 9, 22))
>NodeBase : Symbol(NodeBase, Decl(explicitMembersBeforeInherited.ts, 3, 69))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 9, 22))

type: 'virtual';
>type : Symbol(VirtualNode.type, Decl(explicitMembersBeforeInherited.ts, 9, 46))
}

interface TopNode<L> extends NodeBase<L> {
>TopNode : Symbol(TopNode, Decl(explicitMembersBeforeInherited.ts, 11, 1))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 13, 18))
>NodeBase : Symbol(NodeBase, Decl(explicitMembersBeforeInherited.ts, 3, 69))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 13, 18))

type: 'top';
>type : Symbol(TopNode.type, Decl(explicitMembersBeforeInherited.ts, 13, 42))
}

interface LineNode<L> extends NodeBase<L> {
>LineNode : Symbol(LineNode, Decl(explicitMembersBeforeInherited.ts, 15, 1))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 17, 19))
>NodeBase : Symbol(NodeBase, Decl(explicitMembersBeforeInherited.ts, 3, 69))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 17, 19))

type: 'line';
>type : Symbol(LineNode.type, Decl(explicitMembersBeforeInherited.ts, 17, 43))
}

interface BlankNode<L> extends NodeBase<L> {
>BlankNode : Symbol(BlankNode, Decl(explicitMembersBeforeInherited.ts, 19, 1))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 21, 20))
>NodeBase : Symbol(NodeBase, Decl(explicitMembersBeforeInherited.ts, 3, 69))
>L : Symbol(L, Decl(explicitMembersBeforeInherited.ts, 21, 20))

type: 'blank';
>type : Symbol(BlankNode.type, Decl(explicitMembersBeforeInherited.ts, 21, 44))
}

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

=== explicitMembersBeforeInherited.ts ===
// https://github.com/microsoft/typescript-go/issues/1968

type IndentationTree<L> = TopNode<L> | VirtualNode<L> | LineNode<L> | BlankNode<L>;
>IndentationTree : IndentationTree<L>

type IndentationSubTree<L> = Exclude<IndentationTree<L>, TopNode<L>>;
>IndentationSubTree : IndentationSubTree<L>

interface NodeBase<L> {
subs: IndentationSubTree<L>[];
>subs : IndentationSubTree<L>[]
}

interface VirtualNode<L> extends NodeBase<L> {
type: 'virtual';
>type : "virtual"
}

interface TopNode<L> extends NodeBase<L> {
type: 'top';
>type : "top"
}

interface LineNode<L> extends NodeBase<L> {
type: 'line';
>type : "line"
}

interface BlankNode<L> extends NodeBase<L> {
type: 'blank';
>type : "blank"
}

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
arrayAssignmentTest1.ts(46,5): error TS2741: Property 'IM1' is missing in type 'undefined[]' but required in type 'I1'.
arrayAssignmentTest1.ts(47,5): error TS2739: Type 'undefined[]' is missing the following properties from type 'C1': IM1, C1M1
arrayAssignmentTest1.ts(48,5): error TS2739: Type 'undefined[]' is missing the following properties from type 'C2': IM1, C1M1, C2M1
arrayAssignmentTest1.ts(48,5): error TS2739: Type 'undefined[]' is missing the following properties from type 'C2': C2M1, IM1, C1M1
arrayAssignmentTest1.ts(49,5): error TS2741: Property 'CM3M1' is missing in type 'undefined[]' but required in type 'C3'.
arrayAssignmentTest1.ts(60,1): error TS2322: Type 'C3[]' is not assignable to type 'I1[]'.
Property 'IM1' is missing in type 'C3' but required in type 'I1'.
Expand All @@ -11,9 +11,9 @@ arrayAssignmentTest1.ts(65,1): error TS2322: Type 'C3[]' is not assignable to ty
arrayAssignmentTest1.ts(68,1): error TS2322: Type 'C1[]' is not assignable to type 'C2[]'.
Property 'C2M1' is missing in type 'C1' but required in type 'C2'.
arrayAssignmentTest1.ts(69,1): error TS2322: Type 'I1[]' is not assignable to type 'C2[]'.
Type 'I1' is missing the following properties from type 'C2': C1M1, C2M1
Type 'I1' is missing the following properties from type 'C2': C2M1, C1M1
arrayAssignmentTest1.ts(70,1): error TS2322: Type 'C3[]' is not assignable to type 'C2[]'.
Type 'C3' is missing the following properties from type 'C2': IM1, C1M1, C2M1
Type 'C3' is missing the following properties from type 'C2': C2M1, IM1, C1M1
arrayAssignmentTest1.ts(75,1): error TS2322: Type 'C2[]' is not assignable to type 'C3[]'.
Property 'CM3M1' is missing in type 'C2' but required in type 'C3'.
arrayAssignmentTest1.ts(76,1): error TS2322: Type 'C1[]' is not assignable to type 'C3[]'.
Expand Down Expand Up @@ -83,7 +83,7 @@ arrayAssignmentTest1.ts(85,1): error TS2740: Type 'I1' is missing the following
!!! error TS2739: Type 'undefined[]' is missing the following properties from type 'C1': IM1, C1M1
var c2_error: C2 = []; // should be an error - is
~~~~~~~~
!!! error TS2739: Type 'undefined[]' is missing the following properties from type 'C2': IM1, C1M1, C2M1
!!! error TS2739: Type 'undefined[]' is missing the following properties from type 'C2': C2M1, IM1, C1M1
var c3_error: C3 = []; // should be an error - is
~~~~~~~~
!!! error TS2741: Property 'CM3M1' is missing in type 'undefined[]' but required in type 'C3'.
Expand Down Expand Up @@ -125,11 +125,11 @@ arrayAssignmentTest1.ts(85,1): error TS2740: Type 'I1' is missing the following
arr_c2 = arr_i1; // should be an error - subtype relationship - is
~~~~~~
!!! error TS2322: Type 'I1[]' is not assignable to type 'C2[]'.
!!! error TS2322: Type 'I1' is missing the following properties from type 'C2': C1M1, C2M1
!!! error TS2322: Type 'I1' is missing the following properties from type 'C2': C2M1, C1M1
arr_c2 = arr_c3; // should be an error - is
~~~~~~
!!! error TS2322: Type 'C3[]' is not assignable to type 'C2[]'.
!!! error TS2322: Type 'C3' is missing the following properties from type 'C2': IM1, C1M1, C2M1
!!! error TS2322: Type 'C3' is missing the following properties from type 'C2': C2M1, IM1, C1M1

// "clean up bug" occurs at this point
// if you move these three expressions to another file, they raise an error
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
--- old.arrayAssignmentTest1.errors.txt
+++ new.arrayAssignmentTest1.errors.txt
@@= skipped -0, +0 lines =@@
arrayAssignmentTest1.ts(46,5): error TS2741: Property 'IM1' is missing in type 'undefined[]' but required in type 'I1'.
arrayAssignmentTest1.ts(47,5): error TS2739: Type 'undefined[]' is missing the following properties from type 'C1': IM1, C1M1
-arrayAssignmentTest1.ts(48,5): error TS2739: Type 'undefined[]' is missing the following properties from type 'C2': IM1, C1M1, C2M1
+arrayAssignmentTest1.ts(48,5): error TS2739: Type 'undefined[]' is missing the following properties from type 'C2': C2M1, IM1, C1M1
arrayAssignmentTest1.ts(49,5): error TS2741: Property 'CM3M1' is missing in type 'undefined[]' but required in type 'C3'.
arrayAssignmentTest1.ts(60,1): error TS2322: Type 'C3[]' is not assignable to type 'I1[]'.
Property 'IM1' is missing in type 'C3' but required in type 'I1'.
@@= skipped -10, +10 lines =@@
arrayAssignmentTest1.ts(68,1): error TS2322: Type 'C1[]' is not assignable to type 'C2[]'.
Property 'C2M1' is missing in type 'C1' but required in type 'C2'.
arrayAssignmentTest1.ts(69,1): error TS2322: Type 'I1[]' is not assignable to type 'C2[]'.
- Type 'I1' is missing the following properties from type 'C2': C1M1, C2M1
+ Type 'I1' is missing the following properties from type 'C2': C2M1, C1M1
arrayAssignmentTest1.ts(70,1): error TS2322: Type 'C3[]' is not assignable to type 'C2[]'.
- Type 'C3' is missing the following properties from type 'C2': IM1, C1M1, C2M1
+ Type 'C3' is missing the following properties from type 'C2': C2M1, IM1, C1M1
arrayAssignmentTest1.ts(75,1): error TS2322: Type 'C2[]' is not assignable to type 'C3[]'.
Property 'CM3M1' is missing in type 'C2' but required in type 'C3'.
arrayAssignmentTest1.ts(76,1): error TS2322: Type 'C1[]' is not assignable to type 'C3[]'.
@@= skipped -72, +72 lines =@@
!!! error TS2739: Type 'undefined[]' is missing the following properties from type 'C1': IM1, C1M1
var c2_error: C2 = []; // should be an error - is
~~~~~~~~
-!!! error TS2739: Type 'undefined[]' is missing the following properties from type 'C2': IM1, C1M1, C2M1
+!!! error TS2739: Type 'undefined[]' is missing the following properties from type 'C2': C2M1, IM1, C1M1
var c3_error: C3 = []; // should be an error - is
~~~~~~~~
!!! error TS2741: Property 'CM3M1' is missing in type 'undefined[]' but required in type 'C3'.
@@= skipped -42, +42 lines =@@
arr_c2 = arr_i1; // should be an error - subtype relationship - is
~~~~~~
!!! error TS2322: Type 'I1[]' is not assignable to type 'C2[]'.
-!!! error TS2322: Type 'I1' is missing the following properties from type 'C2': C1M1, C2M1
+!!! error TS2322: Type 'I1' is missing the following properties from type 'C2': C2M1, C1M1
arr_c2 = arr_c3; // should be an error - is
~~~~~~
!!! error TS2322: Type 'C3[]' is not assignable to type 'C2[]'.
-!!! error TS2322: Type 'C3' is missing the following properties from type 'C2': IM1, C1M1, C2M1
+!!! error TS2322: Type 'C3' is missing the following properties from type 'C2': C2M1, IM1, C1M1

// "clean up bug" occurs at this point
// if you move these three expressions to another file, they raise an error
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts(19,64): error TS2741: Property 'z' is missing in type 'B' but required in type 'C'.
chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts(19,81): error TS2739: Type 'A' is missing the following properties from type 'C': y, z
chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts(19,81): error TS2739: Type 'A' is missing the following properties from type 'C': z, y


==== chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts (2 errors) ====
Expand Down Expand Up @@ -27,5 +27,5 @@ chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts(19,81): error TS
!!! related TS2728 chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts:15:5: 'z' is declared here.
!!! related TS6502 chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts:3:27: The expected type comes from the return type of this signature.
~~~~~
!!! error TS2739: Type 'A' is missing the following properties from type 'C': y, z
!!! error TS2739: Type 'A' is missing the following properties from type 'C': z, y
!!! related TS6502 chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts:3:27: The expected type comes from the return type of this signature.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--- old.chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.errors.txt
+++ new.chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.errors.txt
@@= skipped -0, +0 lines =@@
chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts(19,64): error TS2741: Property 'z' is missing in type 'B' but required in type 'C'.
-chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts(19,81): error TS2739: Type 'A' is missing the following properties from type 'C': y, z
+chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts(19,81): error TS2739: Type 'A' is missing the following properties from type 'C': z, y


==== chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts (2 errors) ====
@@= skipped -26, +26 lines =@@
!!! related TS2728 chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts:15:5: 'z' is declared here.
!!! related TS6502 chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts:3:27: The expected type comes from the return type of this signature.
~~~~~
-!!! error TS2739: Type 'A' is missing the following properties from type 'C': y, z
+!!! error TS2739: Type 'A' is missing the following properties from type 'C': z, y
!!! related TS6502 chainedCallsWithTypeParameterConstrainedToOtherTypeParameter.ts:3:27: The expected type comes from the return type of this signature.
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,17 @@ export declare class FooItem {
export type Constructor<T> = new (...args: any[]) => T;
export declare function WithTags<T extends Constructor<FooItem>>(Base: T): {
new (...args: any[]): {
tags(): void;
foo(): void;
name?: string;
tags(): void;
};
getTags(): void;
} & T;
declare const Test_base: {
new (...args: any[]): {
tags(): void;
foo(): void;
name?: string;
tags(): void;
};
getTags(): void;
} & typeof FooItem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,24 @@
+ tags(c: any): any;
};
};
export declare class FooItem {
export declare class FooItem {
@@= skipped -10, +10 lines =@@
export type Constructor<T> = new (...args: any[]) => T;
export declare function WithTags<T extends Constructor<FooItem>>(Base: T): {
new (...args: any[]): {
+ tags(): void;
foo(): void;
name?: string;
- tags(): void;
};
getTags(): void;
} & T;
declare const Test_base: {
new (...args: any[]): {
+ tags(): void;
foo(): void;
name?: string;
- tags(): void;
};
getTags(): void;
} & typeof FooItem;
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,19 @@ export declare class FooItem {
export type Constructor<T> = new (...args: any[]) => T;
export declare function WithTags<T extends Constructor<FooItem>>(Base: T): {
new (...args: any[]): {
tags(): void;
foo(): void;
name?: string;
property: string;
tags(): void;
};
getTags(): void;
} & T;
declare const Test_base: {
new (...args: any[]): {
tags(): void;
foo(): void;
name?: string;
property: string;
tags(): void;
};
getTags(): void;
} & typeof FooItem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,19 @@
+export type Constructor<T> = new (...args: any[]) => T;
+export declare function WithTags<T extends Constructor<FooItem>>(Base: T): {
+ new (...args: any[]): {
+ tags(): void;
+ foo(): void;
+ name?: string;
+ property: string;
+ tags(): void;
+ };
+ getTags(): void;
+} & T;
+declare const Test_base: {
+ new (...args: any[]): {
+ tags(): void;
+ foo(): void;
+ name?: string;
+ property: string;
+ tags(): void;
+ };
+ getTags(): void;
+} & typeof FooItem;
Expand Down
Loading