Add TSAssertsKeyword support
MODIFY
packages/@romejs/js-ast/typescript/TSTypePredicate.ts
packages/@romejs/js-ast/typescript/TSTypePredicate.ts
@@ -10,8 +10,9 @@ import {createBuilder} from '../utils';
export type TSTypePredicate = JSNodeBase & {
type: 'TSTypePredicate';
+ asserts: boolean;
parameterName: Identifier | TSThisType;
- typeAnnotation: AnyPrimaryType;
+ typeAnnotation?: AnyPrimaryType;
};
export const tsTypePredicate = createBuilder<TSTypePredicate>(

ADD
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/arrow-function/asserts-with-predicate-types/input.ts
+(value: unknown): asserts value is string => {};

ADD
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/arrow-function/asserts-with-predicate-types/output.txt
+Program {
+ comments: Array []
+ diagnostics: Array []
+ directives: Array []
+ filename: '..'
+ hasHoistedVars: false
+ interpreter: undefined
+ mtime: undefined
+ sourceType: 'module'
+ syntax: Array ['ts']
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 0
+ index: 49
+ line: 2
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ body: Array [
+ ExpressionStatement {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 48
+ index: 48
+ line: 1
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ expression: ArrowFunctionExpression {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 47
+ index: 47
+ line: 1
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ body: BlockStatement {
+ body: Array []
+ directives: Array []
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 47
+ index: 47
+ line: 1
+ }
+ start: Object {
+ column: 45
+ index: 45
+ line: 1
+ }
+ }
+ }
+ head: FunctionHead {
+ async: false
+ hasHoistedVars: false
+ predicate: undefined
+ rest: undefined
+ thisType: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 45
+ index: 45
+ line: 1
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ returnType: TSTypePredicate {
+ asserts: true
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 41
+ index: 41
+ line: 1
+ }
+ start: Object {
+ column: 26
+ index: 26
+ line: 1
+ }
+ }
+ typeAnnotation: StringKeywordTypeAnnotation {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 41
+ index: 41
+ line: 1
+ }
+ start: Object {
+ column: 35
+ index: 35
+ line: 1
+ }
+ }
+ }
+ parameterName: Identifier {
+ name: 'value'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 31
+ index: 31
+ line: 1
+ }
+ start: Object {
+ column: 26
+ index: 26
+ line: 1
+ }
+ }
+ }
+ }
+ params: Array [
+ BindingIdentifier {
+ name: 'value'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 44
+ index: 44
+ line: 1
+ }
+ start: Object {
+ column: 45
+ index: 45
+ line: 1
+ }
+ }
+ meta: PatternMeta {
+ optional: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 44
+ index: 44
+ line: 1
+ }
+ start: Object {
+ column: 45
+ index: 45
+ line: 1
+ }
+ }
+ typeAnnotation: UnknownKeywordTypeAnnotation {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 15
+ index: 15
+ line: 1
+ }
+ start: Object {
+ column: 8
+ index: 8
+ line: 1
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file

ADD
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/arrow-function/asserts/input.ts
+(value: unknown): asserts value => {};

ADD
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/arrow-function/asserts/output.txt
+Program {
+ comments: Array []
+ diagnostics: Array []
+ directives: Array []
+ filename: '..'
+ hasHoistedVars: false
+ interpreter: undefined
+ mtime: undefined
+ sourceType: 'module'
+ syntax: Array ['ts']
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 0
+ index: 39
+ line: 2
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ body: Array [
+ ExpressionStatement {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 38
+ index: 38
+ line: 1
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ expression: ArrowFunctionExpression {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 37
+ index: 37
+ line: 1
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ body: BlockStatement {
+ body: Array []
+ directives: Array []
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 37
+ index: 37
+ line: 1
+ }
+ start: Object {
+ column: 35
+ index: 35
+ line: 1
+ }
+ }
+ }
+ head: FunctionHead {
+ async: false
+ hasHoistedVars: false
+ predicate: undefined
+ rest: undefined
+ thisType: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 35
+ index: 35
+ line: 1
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ returnType: TSTypePredicate {
+ asserts: true
+ typeAnnotation: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 31
+ index: 31
+ line: 1
+ }
+ start: Object {
+ column: 16
+ index: 16
+ line: 1
+ }
+ }
+ parameterName: Identifier {
+ name: 'value'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 31
+ index: 31
+ line: 1
+ }
+ start: Object {
+ column: 26
+ index: 26
+ line: 1
+ }
+ }
+ }
+ }
+ params: Array [
+ BindingIdentifier {
+ name: 'value'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 34
+ index: 34
+ line: 1
+ }
+ start: Object {
+ column: 35
+ index: 35
+ line: 1
+ }
+ }
+ meta: PatternMeta {
+ optional: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 34
+ index: 34
+ line: 1
+ }
+ start: Object {
+ column: 35
+ index: 35
+ line: 1
+ }
+ }
+ typeAnnotation: UnknownKeywordTypeAnnotation {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 15
+ index: 15
+ line: 1
+ }
+ start: Object {
+ column: 8
+ index: 8
+ line: 1
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file

MODIFY
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/arrow-function/predicate-types/output.txt
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/arrow-function/predicate-types/output.txt
@@ -86,6 +86,7 @@ Program {
}
}
returnType: TSTypePredicate {
+ asserts: false
loc: Object {
filename: '..'
end: Object {

MODIFY
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/class/predicate-types/output.txt
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/class/predicate-types/output.txt
@@ -184,6 +184,7 @@ Program {
}
}
returnType: TSTypePredicate {
+ asserts: false
loc: Object {
filename: '..'
end: Object {
@@ -315,6 +316,7 @@ Program {
}
}
returnType: TSTypePredicate {
+ asserts: false
loc: Object {
filename: '..'
end: Object {

ADD
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/function/asserts-with-predicate-types/input.ts
+function f(x: any): asserts x is string {}
+(function(x: any): asserts x is string {});

ADD
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/function/asserts-with-predicate-types/output.txt
+Program {
+ comments: Array []
+ diagnostics: Array []
+ directives: Array []
+ filename: '..'
+ hasHoistedVars: false
+ interpreter: undefined
+ mtime: undefined
+ sourceType: 'module'
+ syntax: Array ['ts']
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 0
+ index: 87
+ line: 3
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ body: Array [
+ FunctionDeclaration {
+ id: BindingIdentifier {
+ name: 'f'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 10
+ index: 10
+ line: 1
+ }
+ start: Object {
+ column: 9
+ index: 9
+ line: 1
+ }
+ }
+ }
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 42
+ index: 42
+ line: 1
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ body: BlockStatement {
+ body: Array []
+ directives: Array []
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 42
+ index: 42
+ line: 1
+ }
+ start: Object {
+ column: 40
+ index: 40
+ line: 1
+ }
+ }
+ }
+ head: FunctionHead {
+ async: false
+ generator: false
+ hasHoistedVars: false
+ predicate: undefined
+ rest: undefined
+ thisType: undefined
+ typeParameters: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 40
+ index: 40
+ line: 1
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ returnType: TSTypePredicate {
+ asserts: true
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 39
+ index: 39
+ line: 1
+ }
+ start: Object {
+ column: 28
+ index: 28
+ line: 1
+ }
+ }
+ typeAnnotation: StringKeywordTypeAnnotation {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 39
+ index: 39
+ line: 1
+ }
+ start: Object {
+ column: 33
+ index: 33
+ line: 1
+ }
+ }
+ }
+ parameterName: Identifier {
+ name: 'x'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 29
+ index: 29
+ line: 1
+ }
+ start: Object {
+ column: 28
+ index: 28
+ line: 1
+ }
+ }
+ }
+ }
+ params: Array [
+ BindingIdentifier {
+ name: 'x'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 12
+ index: 12
+ line: 1
+ }
+ start: Object {
+ column: 11
+ index: 11
+ line: 1
+ }
+ }
+ meta: PatternMeta {
+ optional: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 17
+ index: 17
+ line: 1
+ }
+ start: Object {
+ column: 11
+ index: 11
+ line: 1
+ }
+ }
+ typeAnnotation: AnyKeywordTypeAnnotation {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 17
+ index: 17
+ line: 1
+ }
+ start: Object {
+ column: 14
+ index: 14
+ line: 1
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ ExpressionStatement {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 43
+ index: 86
+ line: 2
+ }
+ start: Object {
+ column: 0
+ index: 43
+ line: 2
+ }
+ }
+ expression: FunctionExpression {
+ id: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 41
+ index: 84
+ line: 2
+ }
+ start: Object {
+ column: 1
+ index: 44
+ line: 2
+ }
+ }
+ body: BlockStatement {
+ body: Array []
+ directives: Array []
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 41
+ index: 84
+ line: 2
+ }
+ start: Object {
+ column: 39
+ index: 82
+ line: 2
+ }
+ }
+ }
+ head: FunctionHead {
+ async: false
+ generator: false
+ hasHoistedVars: false
+ predicate: undefined
+ rest: undefined
+ thisType: undefined
+ typeParameters: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 39
+ index: 82
+ line: 2
+ }
+ start: Object {
+ column: 1
+ index: 44
+ line: 2
+ }
+ }
+ returnType: TSTypePredicate {
+ asserts: true
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 38
+ index: 81
+ line: 2
+ }
+ start: Object {
+ column: 27
+ index: 70
+ line: 2
+ }
+ }
+ typeAnnotation: StringKeywordTypeAnnotation {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 38
+ index: 81
+ line: 2
+ }
+ start: Object {
+ column: 32
+ index: 75
+ line: 2
+ }
+ }
+ }
+ parameterName: Identifier {
+ name: 'x'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 28
+ index: 71
+ line: 2
+ }
+ start: Object {
+ column: 27
+ index: 70
+ line: 2
+ }
+ }
+ }
+ }
+ params: Array [
+ BindingIdentifier {
+ name: 'x'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 11
+ index: 54
+ line: 2
+ }
+ start: Object {
+ column: 10
+ index: 53
+ line: 2
+ }
+ }
+ meta: PatternMeta {
+ optional: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 16
+ index: 59
+ line: 2
+ }
+ start: Object {
+ column: 10
+ index: 53
+ line: 2
+ }
+ }
+ typeAnnotation: AnyKeywordTypeAnnotation {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 16
+ index: 59
+ line: 2
+ }
+ start: Object {
+ column: 13
+ index: 56
+ line: 2
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file

ADD
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/function/asserts/input.ts
+function f(x: any): asserts x {}
+(function(x: any): asserts x {});

ADD
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/function/asserts/output.txt
+Program {
+ comments: Array []
+ diagnostics: Array []
+ directives: Array []
+ filename: '..'
+ hasHoistedVars: false
+ interpreter: undefined
+ mtime: undefined
+ sourceType: 'module'
+ syntax: Array ['ts']
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 0
+ index: 67
+ line: 3
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ body: Array [
+ FunctionDeclaration {
+ id: BindingIdentifier {
+ name: 'f'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 10
+ index: 10
+ line: 1
+ }
+ start: Object {
+ column: 9
+ index: 9
+ line: 1
+ }
+ }
+ }
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 32
+ index: 32
+ line: 1
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ body: BlockStatement {
+ body: Array []
+ directives: Array []
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 32
+ index: 32
+ line: 1
+ }
+ start: Object {
+ column: 30
+ index: 30
+ line: 1
+ }
+ }
+ }
+ head: FunctionHead {
+ async: false
+ generator: false
+ hasHoistedVars: false
+ predicate: undefined
+ rest: undefined
+ thisType: undefined
+ typeParameters: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 30
+ index: 30
+ line: 1
+ }
+ start: Object {
+ column: 0
+ index: 0
+ line: 1
+ }
+ }
+ returnType: TSTypePredicate {
+ asserts: true
+ typeAnnotation: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 29
+ index: 29
+ line: 1
+ }
+ start: Object {
+ column: 18
+ index: 18
+ line: 1
+ }
+ }
+ parameterName: Identifier {
+ name: 'x'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 29
+ index: 29
+ line: 1
+ }
+ start: Object {
+ column: 28
+ index: 28
+ line: 1
+ }
+ }
+ }
+ }
+ params: Array [
+ BindingIdentifier {
+ name: 'x'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 12
+ index: 12
+ line: 1
+ }
+ start: Object {
+ column: 11
+ index: 11
+ line: 1
+ }
+ }
+ meta: PatternMeta {
+ optional: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 17
+ index: 17
+ line: 1
+ }
+ start: Object {
+ column: 11
+ index: 11
+ line: 1
+ }
+ }
+ typeAnnotation: AnyKeywordTypeAnnotation {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 17
+ index: 17
+ line: 1
+ }
+ start: Object {
+ column: 14
+ index: 14
+ line: 1
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ ExpressionStatement {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 33
+ index: 66
+ line: 2
+ }
+ start: Object {
+ column: 0
+ index: 33
+ line: 2
+ }
+ }
+ expression: FunctionExpression {
+ id: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 31
+ index: 64
+ line: 2
+ }
+ start: Object {
+ column: 1
+ index: 34
+ line: 2
+ }
+ }
+ body: BlockStatement {
+ body: Array []
+ directives: Array []
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 31
+ index: 64
+ line: 2
+ }
+ start: Object {
+ column: 29
+ index: 62
+ line: 2
+ }
+ }
+ }
+ head: FunctionHead {
+ async: false
+ generator: false
+ hasHoistedVars: false
+ predicate: undefined
+ rest: undefined
+ thisType: undefined
+ typeParameters: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 29
+ index: 62
+ line: 2
+ }
+ start: Object {
+ column: 1
+ index: 34
+ line: 2
+ }
+ }
+ returnType: TSTypePredicate {
+ asserts: true
+ typeAnnotation: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 28
+ index: 61
+ line: 2
+ }
+ start: Object {
+ column: 17
+ index: 50
+ line: 2
+ }
+ }
+ parameterName: Identifier {
+ name: 'x'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 28
+ index: 61
+ line: 2
+ }
+ start: Object {
+ column: 27
+ index: 60
+ line: 2
+ }
+ }
+ }
+ }
+ params: Array [
+ BindingIdentifier {
+ name: 'x'
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 11
+ index: 44
+ line: 2
+ }
+ start: Object {
+ column: 10
+ index: 43
+ line: 2
+ }
+ }
+ meta: PatternMeta {
+ optional: undefined
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 16
+ index: 49
+ line: 2
+ }
+ start: Object {
+ column: 10
+ index: 43
+ line: 2
+ }
+ }
+ typeAnnotation: AnyKeywordTypeAnnotation {
+ loc: Object {
+ filename: '..'
+ end: Object {
+ column: 16
+ index: 49
+ line: 2
+ }
+ start: Object {
+ column: 13
+ index: 46
+ line: 2
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file

MODIFY
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/function/predicate-types/output.txt
packages/@romejs/js-parser/__rtests__/__rfixtures__/typescript/function/predicate-types/output.txt
@@ -91,6 +91,7 @@ Program {
}
}
returnType: TSTypePredicate {
+ asserts: false
loc: Object {
filename: '..'
end: Object {
@@ -255,6 +256,7 @@ Program {
}
}
returnType: TSTypePredicate {
+ asserts: false
loc: Object {
filename: '..'
end: Object {

MODIFY
packages/@romejs/js-parser/parser/typescript.ts
packages/@romejs/js-parser/parser/typescript.ts
@@ -364,6 +364,7 @@ function parseTSThisTypePredicate(
return parser.finishNode(start, {
type: 'TSTypePredicate',
+ asserts: false,
parameterName,
typeAnnotation,
});
@@ -1291,27 +1292,42 @@ export function parseTSTypeOrTypePredicateAnnotation(
parser: JSParser,
returnToken: TokenType,
): AnyTSPrimary {
- const start = parser.getPosition();
+ let start = parser.getPosition();
parser.pushScope('TYPE', true);
parser.expect(returnToken);
+ let hasAsserts = parser.eatContextual('asserts');
+ let parameterName: Identifier;
let typePredicateVariable;
if (tsIsIdentifier(parser)) {
typePredicateVariable = tryTSParse(parser, parseTSTypePredicatePrefix);
}
if (typePredicateVariable === undefined) {
+ if (hasAsserts) {
+ parameterName = parseIdentifier(parser);
+ if (parameterName === undefined) {
+ throw Error('Should have an identifier after asserts');
+ }
+ } else {
parser.popScope('TYPE');
return parseTSTypeAnnotation(parser, /* eatColon */ false, start);
}
+ } else {
+ parameterName = typePredicateVariable;
+ }
- const type = parseTSTypeAnnotation(parser, /* eatColon */ false);
+ let type;
+ if (typePredicateVariable) {
+ type = parseTSTypeAnnotation(parser, /* eatColon */ false);
+ start = parser.getLoc(typePredicateVariable).start;
+ }
- const typePredicateStart = parser.getLoc(typePredicateVariable).start;
parser.popScope('TYPE');
- return parser.finishNode(typePredicateStart, {
+ return parser.finishNode(start, {
type: 'TSTypePredicate',
- parameterName: typePredicateVariable,
+ asserts: hasAsserts,
+ parameterName,
typeAnnotation: type,
});
}

Add TSAssertsKeyword support