Skip to content

Commit

Permalink
Allow this when it appears in this is T positions
Browse files Browse the repository at this point in the history
  • Loading branch information
RyanCavanaugh committed Jul 16, 2024
1 parent bf39ecc commit 54a83b9
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 153 deletions.
4 changes: 3 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19673,7 +19673,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (isJSConstructor(container) && isNodeDescendantOf(node, container.body)) {
return getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(container)).thisType!;
}
error(node, Diagnostics.A_this_type_is_available_only_in_a_non_static_member_of_a_class_or_interface);
if (node.parent.kind !== SyntaxKind.TypePredicate) {
error(node, Diagnostics.A_this_type_is_available_only_in_a_non_static_member_of_a_class_or_interface);
}
return errorType;
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ export const obj = {
>this as {} : {}
> : ^^
>this : any
> : ^^^

return dis.a != null && dis.b != null && dis.c != null;
>dis.a != null && dis.b != null && dis.c != null : boolean
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ export const obj = {
>this as {} : {}
> : ^^
>this : any
> : ^^^

return dis.a != null && dis.b != null && dis.c != null;
>dis.a != null && dis.b != null && dis.c != null : boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,113 +107,3 @@ export declare const thing: {
readonly [Symbol.unscopables]?: boolean;
};
};


//// [DtsFileErrors]


mappedTypeWithAsClauseAndLateBoundProperty2.d.ts(27,118): error TS2526: A 'this' type is available only in a non-static member of a class or interface.


==== mappedTypeWithAsClauseAndLateBoundProperty2.d.ts (1 errors) ====
export declare const thing: {
[x: number]: number;
toString: () => string;
toLocaleString: {
(): string;
(locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string;
};
pop: () => number;
push: (...items: number[]) => number;
concat: {
(...items: ConcatArray<number>[]): number[];
(...items: (number | ConcatArray<number>)[]): number[];
};
join: (separator?: string) => string;
reverse: () => number[];
shift: () => number;
slice: (start?: number, end?: number) => number[];
sort: (compareFn?: (a: number, b: number) => number) => number[];
splice: {
(start: number, deleteCount?: number): number[];
(start: number, deleteCount: number, ...items: number[]): number[];
};
unshift: (...items: number[]) => number;
indexOf: (searchElement: number, fromIndex?: number) => number;
lastIndexOf: (searchElement: number, fromIndex?: number) => number;
every: {
<S extends number>(predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[];
~~~~
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
(predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean;
};
some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean;
forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void;
map: <U>(callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[];
filter: {
<S extends number>(predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): S[];
(predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[];
};
reduce: {
(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number;
(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number;
<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U;
};
reduceRight: {
(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number;
(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number;
<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U;
};
find: {
<S extends number>(predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S;
(predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number;
};
findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number;
fill: (value: number, start?: number, end?: number) => number[];
copyWithin: (target: number, start: number, end?: number) => number[];
entries: () => IterableIterator<[number, number]>;
keys: () => IterableIterator<number>;
values: () => IterableIterator<number>;
includes: (searchElement: number, fromIndex?: number) => boolean;
flatMap: <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[];
flat: <A, D extends number = 1>(this: A, depth?: D) => FlatArray<A, D>[];
[Symbol.iterator]: () => IterableIterator<number>;
readonly [Symbol.unscopables]: {
[x: number]: boolean;
length?: boolean;
toString?: boolean;
toLocaleString?: boolean;
pop?: boolean;
push?: boolean;
concat?: boolean;
join?: boolean;
reverse?: boolean;
shift?: boolean;
slice?: boolean;
sort?: boolean;
splice?: boolean;
unshift?: boolean;
indexOf?: boolean;
lastIndexOf?: boolean;
every?: boolean;
some?: boolean;
forEach?: boolean;
map?: boolean;
filter?: boolean;
reduce?: boolean;
reduceRight?: boolean;
find?: boolean;
findIndex?: boolean;
fill?: boolean;
copyWithin?: boolean;
entries?: boolean;
keys?: boolean;
values?: boolean;
includes?: boolean;
flatMap?: boolean;
flat?: boolean;
[Symbol.iterator]?: boolean;
readonly [Symbol.unscopables]?: boolean;
};
};

18 changes: 18 additions & 0 deletions tests/baselines/reference/thisPredicateInObjectLiteral.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//// [tests/cases/compiler/thisPredicateInObjectLiteral.ts] ////

//// [thisPredicateInObjectLiteral.ts]
// Should be OK
const foo2 = {
isNumber(): this is { b: string } {
return true;
},
};

//// [thisPredicateInObjectLiteral.js]
"use strict";
// Should be OK
var foo2 = {
isNumber: function () {
return true;
},
};
14 changes: 14 additions & 0 deletions tests/baselines/reference/thisPredicateInObjectLiteral.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//// [tests/cases/compiler/thisPredicateInObjectLiteral.ts] ////

=== thisPredicateInObjectLiteral.ts ===
// Should be OK
const foo2 = {
>foo2 : Symbol(foo2, Decl(thisPredicateInObjectLiteral.ts, 1, 5))

isNumber(): this is { b: string } {
>isNumber : Symbol(isNumber, Decl(thisPredicateInObjectLiteral.ts, 1, 14))
>b : Symbol(b, Decl(thisPredicateInObjectLiteral.ts, 2, 25))

return true;
},
};
22 changes: 22 additions & 0 deletions tests/baselines/reference/thisPredicateInObjectLiteral.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//// [tests/cases/compiler/thisPredicateInObjectLiteral.ts] ////

=== thisPredicateInObjectLiteral.ts ===
// Should be OK
const foo2 = {
>foo2 : { isNumber(): this is { b: string; }; }
> : ^^^^^^^^^^^^^^ ^^^
>{ isNumber(): this is { b: string } { return true; },} : { isNumber(): this is { b: string; }; }
> : ^^^^^^^^^^^^^^ ^^^

isNumber(): this is { b: string } {
>isNumber : () => this is { b: string; }
> : ^^^^^^
>b : string
> : ^^^^^^

return true;
>true : true
> : ^^^^

},
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ typeGuardFunctionOfFormThisErrors.ts(26,1): error TS2322: Type '() => this is Le
typeGuardFunctionOfFormThisErrors.ts(27,1): error TS2322: Type '() => this is FollowerGuard' is not assignable to type '() => this is LeadGuard'.
Type predicate 'this is FollowerGuard' is not assignable to 'this is LeadGuard'.
Property 'lead' is missing in type 'FollowerGuard' but required in type 'LeadGuard'.
typeGuardFunctionOfFormThisErrors.ts(29,32): error TS2526: A 'this' type is available only in a non-static member of a class or interface.
typeGuardFunctionOfFormThisErrors.ts(55,7): error TS2339: Property 'follow' does not exist on type 'RoyalGuard'.
typeGuardFunctionOfFormThisErrors.ts(58,7): error TS2339: Property 'lead' does not exist on type 'RoyalGuard'.


==== typeGuardFunctionOfFormThisErrors.ts (7 errors) ====
==== typeGuardFunctionOfFormThisErrors.ts (6 errors) ====
class RoyalGuard {
isLeader(): this is LeadGuard {
return this instanceof LeadGuard;
Expand Down Expand Up @@ -65,8 +64,6 @@ typeGuardFunctionOfFormThisErrors.ts(58,7): error TS2339: Property 'lead' does n
!!! related TS2728 typeGuardFunctionOfFormThisErrors.ts:11:5: 'lead' is declared here.

function invalidGuard(c: any): this is number {
~~~~
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
return false;
}

Expand Down
8 changes: 8 additions & 0 deletions tests/cases/compiler/thisPredicateInObjectLiteral.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// @strict: true

// Should be OK
const foo2 = {
isNumber(): this is { b: string } {
return true;
},
};

0 comments on commit 54a83b9

Please sign in to comment.