Skip to content

[WIP] Higher kinded types #23809

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

Closed
wants to merge 8 commits into from
Closed
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
2 changes: 2 additions & 0 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1409,6 +1409,7 @@ namespace ts {
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.MappedType:
case SyntaxKind.TypeParameter:
return ContainerFlags.IsContainer | ContainerFlags.HasLocals;

case SyntaxKind.SourceFile:
Expand Down Expand Up @@ -1530,6 +1531,7 @@ namespace ts {
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.MappedType:
case SyntaxKind.TypeParameter:
// All the children of these container types are never visible through another
// symbol (i.e. through another symbol's 'exports' or 'members'). Instead,
// they're only accessed 'lexically' (i.e. from code that exists underneath
Expand Down
289 changes: 259 additions & 30 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ namespace ts {
visitNode(cbNode, (<QualifiedName>node).right);
case SyntaxKind.TypeParameter:
return visitNode(cbNode, (<TypeParameterDeclaration>node).name) ||
visitNodes(cbNode, cbNodes, (<TypeParameterDeclaration>node).typeParameters) ||
visitNode(cbNode, (<TypeParameterDeclaration>node).constraint) ||
visitNode(cbNode, (<TypeParameterDeclaration>node).default) ||
visitNode(cbNode, (<TypeParameterDeclaration>node).expression);
Expand Down Expand Up @@ -1608,7 +1609,8 @@ namespace ts {
return isVariableDeclaratorListTerminator();
case ParsingContext.TypeParameters:
// Tokens other than '>' are here for better error recovery
return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.OpenBraceToken ||
token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword || token() === SyntaxKind.SemicolonToken;
case ParsingContext.ArgumentExpressions:
// Tokens other than ')' are here for better error recovery
return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.SemicolonToken;
Expand Down Expand Up @@ -2366,6 +2368,7 @@ namespace ts {
function parseTypeParameter(): TypeParameterDeclaration {
const node = <TypeParameterDeclaration>createNode(SyntaxKind.TypeParameter);
node.name = parseIdentifier();
node.typeParameters = parseTypeParameters();
if (parseOptional(SyntaxKind.ExtendsKeyword)) {
// It's not uncommon for people to write improper constraints to a generic. If the
// user writes a constraint that is an expression and not an actual type, then parse
Expand Down
37 changes: 30 additions & 7 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,7 @@ namespace ts {
kind: SyntaxKind.TypeParameter;
parent: DeclarationWithTypeParameters | InferTypeNode;
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
constraint?: TypeNode;
default?: TypeNode;

Expand Down Expand Up @@ -2055,7 +2056,7 @@ namespace ts {

export type ObjectTypeDeclaration = ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode;

export type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag | JSDocTypedefTag | JSDocCallbackTag | JSDocSignature;
export type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | TypeParameterDeclaration | JSDocTemplateTag | JSDocTypedefTag | JSDocCallbackTag | JSDocSignature;

export interface ClassLikeDeclarationBase extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression;
Expand Down Expand Up @@ -3765,6 +3766,8 @@ namespace ts {
aliasTypeArguments?: Type[]; // Alias type arguments (if any)
/* @internal */
wildcardInstantiation?: Type; // Instantiation with type parameters mapped to wildcard type
/* @internal */
wrapperType?: WrapperType; // wrapper type for this type
}

/* @internal */
Expand Down Expand Up @@ -3813,6 +3816,10 @@ namespace ts {
ReverseMapped = 1 << 11, // Object contains a property from a reverse-mapped type
JsxAttributes = 1 << 12, // Jsx attributes type
MarkerType = 1 << 13, // Marker type used for variance probing
GenericTypeParameter = 1 << 14, // uninstantiated generic type parameter (meaning a type parameter that has its own type parameters)
/* @internal */
Wrapper = 1 << 15, // wrapper for mapped GenericTypeParameters, which is needed to avoid instantiation order problems in some cases in getInferredType()

ClassOrInterface = Class | Interface
}

Expand Down Expand Up @@ -3855,8 +3862,9 @@ namespace ts {
* explicit "this" argument.
*/
export interface TypeReference extends ObjectType {
target: GenericType; // Type reference target
typeArguments?: Type[]; // Type reference type arguments (undefined if none)
target: GenericType; // Type reference target
typeArguments?: Type[]; // Type reference type arguments (undefined if none)
typeParameterReference?: boolean; // true if target is a GenericTypeParameter but NOT true if this is the GenericTypeParameter (ie if this === target)
}

/* @internal */
Expand All @@ -3868,7 +3876,7 @@ namespace ts {
Independent = 4, // Unwitnessed type parameter
}

// Generic class and interface types
// Generic class, interface and type parameter types
export interface GenericType extends InterfaceType, TypeReference {
/* @internal */
instantiations: Map<TypeReference>; // Generic instantiation cache
Expand Down Expand Up @@ -3985,13 +3993,28 @@ namespace ts {
/* @internal */
default?: Type;
/* @internal */
target?: TypeParameter; // Instantiation target
original?: TypeParameter; // The type parameter this type parameter was cloned from
/* @internal */
mapper?: TypeMapper; // Instantiation mapper
mapper?: TypeMapper; // mapper for cloned type parameters
/* @internal */
isThisType?: boolean;
/* @internal */
resolvedDefaultType?: Type;
isGeneric?: boolean;
}

// Generic type parameters (TypeFlags.TypeParameter, TypeFlags.Object, ObjectFlags.GenericTypeParameter)
export interface GenericTypeParameter extends GenericType, TypeParameter, InterfaceTypeWithDeclaredMembers {
localTypeParameters: TypeParameter[]; // GenericTypeParameters always have localTypeParameters since that's what distinguishes them from non-generic type parameters.
/* @internal */
original?: GenericTypeParameter; // The type parameter this type parameter was cloned from
/* @internal */
isGeneric: true;
}

/* @internal */
// ObjectFlags.Wrapper
export interface WrapperType extends ObjectType {
wrappedType: Type;
}

// Indexed access types (TypeFlags.IndexedAccess)
Expand Down
1 change: 1 addition & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ namespace ts {
case SyntaxKind.SetAccessor:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.TypeParameter:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocSignature:
Expand Down
2 changes: 2 additions & 0 deletions src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1776,6 +1776,7 @@ namespace ts.Completions {
containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface A<T, |
containingNodeKind === SyntaxKind.ArrayBindingPattern || // var [x, y|
containingNodeKind === SyntaxKind.TypeAliasDeclaration || // type Map, K, |
containingNodeKind === SyntaxKind.TypeParameter || // <T<_T, |
// class A<T, |
// var C = class D<T, |
(isClassLike(parent) &&
Expand Down Expand Up @@ -1803,6 +1804,7 @@ namespace ts.Completions {
containingNodeKind === SyntaxKind.ClassExpression || // var C = class D< |
containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface A< |
containingNodeKind === SyntaxKind.TypeAliasDeclaration || // type List< |
containingNodeKind === SyntaxKind.TypeParameter || // <T< |
isFunctionLikeKind(containingNodeKind);

case SyntaxKind.StaticKeyword:
Expand Down
8 changes: 7 additions & 1 deletion tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ declare namespace ts {
kind: SyntaxKind.TypeParameter;
parent: DeclarationWithTypeParameters | InferTypeNode;
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
constraint?: TypeNode;
default?: TypeNode;
expression?: Expression;
Expand Down Expand Up @@ -1282,7 +1283,7 @@ declare namespace ts {
block: Block;
}
type ObjectTypeDeclaration = ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode;
type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag | JSDocTypedefTag | JSDocCallbackTag | JSDocSignature;
type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | TypeParameterDeclaration | JSDocTemplateTag | JSDocTypedefTag | JSDocCallbackTag | JSDocSignature;
interface ClassLikeDeclarationBase extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression;
name?: Identifier;
Expand Down Expand Up @@ -2210,6 +2211,7 @@ declare namespace ts {
ReverseMapped = 2048,
JsxAttributes = 4096,
MarkerType = 8192,
GenericTypeParameter = 16384,
ClassOrInterface = 3
}
interface ObjectType extends Type {
Expand Down Expand Up @@ -2243,6 +2245,7 @@ declare namespace ts {
interface TypeReference extends ObjectType {
target: GenericType;
typeArguments?: Type[];
typeParameterReference?: boolean;
}
interface GenericType extends InterfaceType, TypeReference {
}
Expand All @@ -2262,6 +2265,9 @@ declare namespace ts {
}
interface TypeParameter extends InstantiableType {
}
interface GenericTypeParameter extends GenericType, TypeParameter, InterfaceTypeWithDeclaredMembers {
localTypeParameters: TypeParameter[];
}
interface IndexedAccessType extends InstantiableType {
objectType: Type;
indexType: Type;
Expand Down
8 changes: 7 additions & 1 deletion tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ declare namespace ts {
kind: SyntaxKind.TypeParameter;
parent: DeclarationWithTypeParameters | InferTypeNode;
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
constraint?: TypeNode;
default?: TypeNode;
expression?: Expression;
Expand Down Expand Up @@ -1282,7 +1283,7 @@ declare namespace ts {
block: Block;
}
type ObjectTypeDeclaration = ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode;
type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag | JSDocTypedefTag | JSDocCallbackTag | JSDocSignature;
type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | TypeParameterDeclaration | JSDocTemplateTag | JSDocTypedefTag | JSDocCallbackTag | JSDocSignature;
interface ClassLikeDeclarationBase extends NamedDeclaration, JSDocContainer {
kind: SyntaxKind.ClassDeclaration | SyntaxKind.ClassExpression;
name?: Identifier;
Expand Down Expand Up @@ -2210,6 +2211,7 @@ declare namespace ts {
ReverseMapped = 2048,
JsxAttributes = 4096,
MarkerType = 8192,
GenericTypeParameter = 16384,
ClassOrInterface = 3
}
interface ObjectType extends Type {
Expand Down Expand Up @@ -2243,6 +2245,7 @@ declare namespace ts {
interface TypeReference extends ObjectType {
target: GenericType;
typeArguments?: Type[];
typeParameterReference?: boolean;
}
interface GenericType extends InterfaceType, TypeReference {
}
Expand All @@ -2262,6 +2265,9 @@ declare namespace ts {
}
interface TypeParameter extends InstantiableType {
}
interface GenericTypeParameter extends GenericType, TypeParameter, InterfaceTypeWithDeclaredMembers {
localTypeParameters: TypeParameter[];
}
interface IndexedAccessType extends InstantiableType {
objectType: Type;
indexType: Type;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//// [getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts]
export declare function f1<T>(cb: <S extends number>(x: S) => T): T;
export declare function f2<T>(cb: <S extends string>(x: S) => T): T;
export declare function f3<T>(cb: <S extends symbol>(x: S) => T): T;
export declare function f4<T>(cb: <S extends number | string | symbol>(x: S) => T): T;
export declare function f5<T, O>(cb: <S extends keyof O>(x: S) => T, obj: O): keyof O;
export declare function f6<T, O>(cb: <S extends string & keyof O>(x: S) => T, obj: O): T;
export declare function f7<T, O>(cb: <S extends Extract<keyof O, string>>(x: S) => T, obj: O): T;

const x1 = f1(x => x);
const expectedx1: number = x1;

let x2 = f2(x => x);
const expectedx2: string = x2;

let x3 = f3(x => x);
const expectedx3: symbol = x3;

let x4 = f4(x => x);
const expectedx4: number | string | symbol = x4;

declare const symProp: unique symbol
declare const obj: {
prop: string,
[symProp]: symbol,
[index: number]: number
}


let x5 = f5((x) => x, obj);
const expectedx5: number | string | symbol = x5;

let x6 = f6(x => x, obj);
const expectedx6: string = x6;

let x7 = f7(x => x, obj);
const expectedx7: string = x7;

//// [getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.js]
"use strict";
exports.__esModule = true;
var x1 = f1(function (x) { return x; });
var expectedx1 = x1;
var x2 = f2(function (x) { return x; });
var expectedx2 = x2;
var x3 = f3(function (x) { return x; });
var expectedx3 = x3;
var x4 = f4(function (x) { return x; });
var expectedx4 = x4;
var x5 = f5(function (x) { return x; }, obj);
var expectedx5 = x5;
var x6 = f6(function (x) { return x; }, obj);
var expectedx6 = x6;
var x7 = f7(function (x) { return x; }, obj);
var expectedx7 = x7;
Loading