mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
feat(7481): Operator to ensure an expression is contextually typed by, and satisfies, some type (#46827)
* feat(7481): add explicit type compatibility check with 'satisfies' expression * Add failing test for lack of intersectioned contextual type * Implement the behavior * Add test corresponding to the 'if' * Add test based on defined scenarios * remove isExpression in favor of using type casting * move tests from compiler to conformance folder * update baseline * add missing contextFlags argument * use asserted type * accept baseline Co-authored-by: Ryan Cavanaugh <ryanca@microsoft.com>
This commit is contained in:
co-authored by
Ryan Cavanaugh
parent
07157914eb
commit
164dddc48e
@@ -27506,6 +27506,8 @@ namespace ts {
|
||||
}
|
||||
case SyntaxKind.NonNullExpression:
|
||||
return getContextualType(parent as NonNullExpression, contextFlags);
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
return getTypeFromTypeNode((parent as SatisfiesExpression).type);
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return tryGetTypeFromEffectiveTypeNode(parent as ExportAssignment);
|
||||
case SyntaxKind.JsxExpression:
|
||||
@@ -32442,6 +32444,20 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkSatisfiesExpression(node: SatisfiesExpression) {
|
||||
checkSourceElement(node.type);
|
||||
|
||||
const targetType = getTypeFromTypeNode(node.type);
|
||||
if (isErrorType(targetType)) {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
const exprType = checkExpression(node.expression);
|
||||
checkTypeAssignableToAndOptionallyElaborate(exprType, targetType, node.type, node.expression, Diagnostics.Type_0_does_not_satisfy_the_expected_type_1);
|
||||
|
||||
return exprType;
|
||||
}
|
||||
|
||||
function checkMetaProperty(node: MetaProperty): Type {
|
||||
checkGrammarMetaProperty(node);
|
||||
|
||||
@@ -35235,6 +35251,8 @@ namespace ts {
|
||||
return checkNonNullAssertion(node as NonNullExpression);
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return checkExpressionWithTypeArguments(node as ExpressionWithTypeArguments);
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
return checkSatisfiesExpression(node as SatisfiesExpression);
|
||||
case SyntaxKind.MetaProperty:
|
||||
return checkMetaProperty(node as MetaProperty);
|
||||
case SyntaxKind.DeleteExpression:
|
||||
|
||||
@@ -1100,7 +1100,7 @@
|
||||
"category": "Error",
|
||||
"code": 1359
|
||||
},
|
||||
"Class constructor may not be a generator.": {
|
||||
"Type '{0}' does not satisfy the expected type '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 1360
|
||||
},
|
||||
@@ -1132,6 +1132,10 @@
|
||||
"category": "Message",
|
||||
"code": 1367
|
||||
},
|
||||
"Class constructor may not be a generator.": {
|
||||
"category": "Error",
|
||||
"code": 1368
|
||||
},
|
||||
"Did you mean '{0}'?": {
|
||||
"category": "Message",
|
||||
"code": 1369
|
||||
@@ -6376,6 +6380,10 @@
|
||||
"category": "Error",
|
||||
"code": 8036
|
||||
},
|
||||
"Type satisfaction expressions can only be used in TypeScript files.": {
|
||||
"category": "Error",
|
||||
"code": 8037
|
||||
},
|
||||
|
||||
"Declaration emit for this file requires using private name '{0}'. An explicit type annotation may unblock declaration emit.": {
|
||||
"category": "Error",
|
||||
|
||||
@@ -1763,6 +1763,8 @@ namespace ts {
|
||||
return emitNonNullExpression(node as NonNullExpression);
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return emitExpressionWithTypeArguments(node as ExpressionWithTypeArguments);
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
return emitSatisfiesExpression(node as SatisfiesExpression);
|
||||
case SyntaxKind.MetaProperty:
|
||||
return emitMetaProperty(node as MetaProperty);
|
||||
case SyntaxKind.SyntheticExpression:
|
||||
@@ -2846,6 +2848,16 @@ namespace ts {
|
||||
writeOperator("!");
|
||||
}
|
||||
|
||||
function emitSatisfiesExpression(node: SatisfiesExpression) {
|
||||
emitExpression(node.expression, /*parenthesizerRules*/ undefined);
|
||||
if (node.type) {
|
||||
writeSpace();
|
||||
writeKeyword("satisfies");
|
||||
writeSpace();
|
||||
emit(node.type);
|
||||
}
|
||||
}
|
||||
|
||||
function emitMetaProperty(node: MetaProperty) {
|
||||
writeToken(node.keywordToken, node.pos, writePunctuation);
|
||||
writePunctuation(".");
|
||||
|
||||
@@ -222,6 +222,8 @@ namespace ts {
|
||||
updateAsExpression,
|
||||
createNonNullExpression,
|
||||
updateNonNullExpression,
|
||||
createSatisfiesExpression,
|
||||
updateSatisfiesExpression,
|
||||
createNonNullChain,
|
||||
updateNonNullChain,
|
||||
createMetaProperty,
|
||||
@@ -3142,6 +3144,26 @@ namespace ts {
|
||||
: node;
|
||||
}
|
||||
|
||||
// @api
|
||||
function createSatisfiesExpression(expression: Expression, type: TypeNode) {
|
||||
const node = createBaseExpression<SatisfiesExpression>(SyntaxKind.SatisfiesExpression);
|
||||
node.expression = expression;
|
||||
node.type = type;
|
||||
node.transformFlags |=
|
||||
propagateChildFlags(node.expression) |
|
||||
propagateChildFlags(node.type) |
|
||||
TransformFlags.ContainsTypeScript;
|
||||
return node;
|
||||
}
|
||||
|
||||
// @api
|
||||
function updateSatisfiesExpression(node: SatisfiesExpression, expression: Expression, type: TypeNode) {
|
||||
return node.expression !== expression
|
||||
|| node.type !== type
|
||||
? update(createSatisfiesExpression(expression, type), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
// @api
|
||||
function createNonNullChain(expression: Expression) {
|
||||
const node = createBaseExpression<NonNullChain>(SyntaxKind.NonNullExpression);
|
||||
@@ -5730,6 +5752,7 @@ namespace ts {
|
||||
case SyntaxKind.ParenthesizedExpression: return updateParenthesizedExpression(outerExpression, expression);
|
||||
case SyntaxKind.TypeAssertionExpression: return updateTypeAssertion(outerExpression, outerExpression.type, expression);
|
||||
case SyntaxKind.AsExpression: return updateAsExpression(outerExpression, expression, outerExpression.type);
|
||||
case SyntaxKind.SatisfiesExpression: return updateSatisfiesExpression(outerExpression, expression, outerExpression.type);
|
||||
case SyntaxKind.NonNullExpression: return updateNonNullExpression(outerExpression, expression);
|
||||
case SyntaxKind.PartiallyEmittedExpression: return updatePartiallyEmittedExpression(outerExpression, expression);
|
||||
}
|
||||
@@ -6465,6 +6488,7 @@ namespace ts {
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return TransformFlags.BindingPatternExcludes;
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
case SyntaxKind.AsExpression:
|
||||
case SyntaxKind.PartiallyEmittedExpression:
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
|
||||
@@ -438,6 +438,10 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.AsExpression;
|
||||
}
|
||||
|
||||
export function isSatisfiesExpression(node: Node): node is SatisfiesExpression {
|
||||
return node.kind === SyntaxKind.SatisfiesExpression;
|
||||
}
|
||||
|
||||
export function isNonNullExpression(node: Node): node is NonNullExpression {
|
||||
return node.kind === SyntaxKind.NonNullExpression;
|
||||
}
|
||||
|
||||
@@ -437,6 +437,7 @@ namespace ts {
|
||||
return (kinds & OuterExpressionKinds.Parentheses) !== 0;
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
case SyntaxKind.AsExpression:
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
return (kinds & OuterExpressionKinds.TypeAssertions) !== 0;
|
||||
case SyntaxKind.NonNullExpression:
|
||||
return (kinds & OuterExpressionKinds.NonNullAssertions) !== 0;
|
||||
|
||||
+11
-3
@@ -393,6 +393,9 @@ namespace ts {
|
||||
[SyntaxKind.NonNullExpression]: function forEachChildInNonNullExpression<T>(node: NonNullExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
|
||||
return visitNode(cbNode, node.expression);
|
||||
},
|
||||
[SyntaxKind.SatisfiesExpression]: function forEachChildInSatisfiesExpression<T>(node: SatisfiesExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
|
||||
return visitNode(cbNode, node.expression) || visitNode(cbNode, node.type);
|
||||
},
|
||||
[SyntaxKind.MetaProperty]: function forEachChildInMetaProperty<T>(node: MetaProperty, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
|
||||
return visitNode(cbNode, node.name);
|
||||
},
|
||||
@@ -841,7 +844,6 @@ namespace ts {
|
||||
if (node === undefined || node.kind <= SyntaxKind.LastToken) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fn = (forEachChildTable as Record<SyntaxKind, ForEachChildFunction<any>>)[node.kind];
|
||||
return fn === undefined ? undefined : fn(node, cbNode, cbNodes);
|
||||
}
|
||||
@@ -5109,7 +5111,7 @@ namespace ts {
|
||||
break;
|
||||
}
|
||||
|
||||
if (token() === SyntaxKind.AsKeyword) {
|
||||
if (token() === SyntaxKind.AsKeyword || token() === SyntaxKind.SatisfiesKeyword) {
|
||||
// Make sure we *do* perform ASI for constructs like this:
|
||||
// var x = foo
|
||||
// as (Bar)
|
||||
@@ -5119,8 +5121,10 @@ namespace ts {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
const keywordKind = token();
|
||||
nextToken();
|
||||
leftOperand = makeAsExpression(leftOperand, parseType());
|
||||
leftOperand = keywordKind === SyntaxKind.SatisfiesKeyword ? makeSatisfiesExpression(leftOperand, parseType()) :
|
||||
makeAsExpression(leftOperand, parseType());
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -5139,6 +5143,10 @@ namespace ts {
|
||||
return getBinaryOperatorPrecedence(token()) > 0;
|
||||
}
|
||||
|
||||
function makeSatisfiesExpression(left: Expression, right: TypeNode): SatisfiesExpression {
|
||||
return finishNode(factory.createSatisfiesExpression(left, right), left.pos);
|
||||
}
|
||||
|
||||
function makeBinaryExpression(left: Expression, operatorToken: BinaryOperatorToken, right: Expression, pos: number): BinaryExpression {
|
||||
return finishNode(factory.createBinaryExpression(left, operatorToken, right), pos);
|
||||
}
|
||||
|
||||
@@ -2372,6 +2372,9 @@ namespace ts {
|
||||
case SyntaxKind.AsExpression:
|
||||
diagnostics.push(createDiagnosticForNode((node as AsExpression).type, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files));
|
||||
return "skip";
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
diagnostics.push(createDiagnosticForNode((node as SatisfiesExpression).type, Diagnostics.Type_satisfaction_expressions_can_only_be_used_in_TypeScript_files));
|
||||
return "skip";
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
Debug.fail(); // Won't parse these in a JS file anyway, as they are interpreted as JSX.
|
||||
}
|
||||
|
||||
@@ -136,6 +136,7 @@ namespace ts {
|
||||
require: SyntaxKind.RequireKeyword,
|
||||
global: SyntaxKind.GlobalKeyword,
|
||||
return: SyntaxKind.ReturnKeyword,
|
||||
satisfies: SyntaxKind.SatisfiesKeyword,
|
||||
set: SyntaxKind.SetKeyword,
|
||||
static: SyntaxKind.StaticKeyword,
|
||||
string: SyntaxKind.StringKeyword,
|
||||
|
||||
@@ -529,6 +529,9 @@ namespace ts {
|
||||
// TypeScript type assertions are removed, but their subtrees are preserved.
|
||||
return visitAssertionExpression(node as AssertionExpression);
|
||||
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
return visitSatisfiesExpression(node as SatisfiesExpression);
|
||||
|
||||
case SyntaxKind.CallExpression:
|
||||
return visitCallExpression(node as CallExpression);
|
||||
|
||||
@@ -1421,6 +1424,11 @@ namespace ts {
|
||||
return factory.createPartiallyEmittedExpression(expression, node);
|
||||
}
|
||||
|
||||
function visitSatisfiesExpression(node: SatisfiesExpression): Expression {
|
||||
const expression = visitNode(node.expression, visitor, isExpression);
|
||||
return factory.createPartiallyEmittedExpression(expression, node);
|
||||
}
|
||||
|
||||
function visitCallExpression(node: CallExpression) {
|
||||
return factory.updateCallExpression(
|
||||
node,
|
||||
|
||||
@@ -181,6 +181,7 @@ namespace ts {
|
||||
RequireKeyword,
|
||||
NumberKeyword,
|
||||
ObjectKeyword,
|
||||
SatisfiesKeyword,
|
||||
SetKeyword,
|
||||
StringKeyword,
|
||||
SymbolKeyword,
|
||||
@@ -274,6 +275,7 @@ namespace ts {
|
||||
NonNullExpression,
|
||||
MetaProperty,
|
||||
SyntheticExpression,
|
||||
SatisfiesExpression,
|
||||
|
||||
// Misc
|
||||
TemplateSpan,
|
||||
@@ -607,6 +609,7 @@ namespace ts {
|
||||
| SyntaxKind.OverrideKeyword
|
||||
| SyntaxKind.RequireKeyword
|
||||
| SyntaxKind.ReturnKeyword
|
||||
| SyntaxKind.SatisfiesKeyword
|
||||
| SyntaxKind.SetKeyword
|
||||
| SyntaxKind.StaticKeyword
|
||||
| SyntaxKind.StringKeyword
|
||||
@@ -1007,6 +1010,7 @@ namespace ts {
|
||||
| ExpressionWithTypeArguments
|
||||
| AsExpression
|
||||
| NonNullExpression
|
||||
| SatisfiesExpression
|
||||
| MetaProperty
|
||||
| TemplateSpan
|
||||
| Block
|
||||
@@ -2815,6 +2819,12 @@ namespace ts {
|
||||
readonly expression: UnaryExpression;
|
||||
}
|
||||
|
||||
export interface SatisfiesExpression extends Expression {
|
||||
readonly kind: SyntaxKind.SatisfiesExpression;
|
||||
readonly expression: Expression;
|
||||
readonly type: TypeNode;
|
||||
}
|
||||
|
||||
export type AssertionExpression =
|
||||
| TypeAssertion
|
||||
| AsExpression
|
||||
@@ -7520,6 +7530,7 @@ namespace ts {
|
||||
export type OuterExpression =
|
||||
| ParenthesizedExpression
|
||||
| TypeAssertion
|
||||
| SatisfiesExpression
|
||||
| AsExpression
|
||||
| NonNullExpression
|
||||
| PartiallyEmittedExpression;
|
||||
@@ -7856,6 +7867,8 @@ namespace ts {
|
||||
updateNonNullChain(node: NonNullChain, expression: Expression): NonNullChain;
|
||||
createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier): MetaProperty;
|
||||
updateMetaProperty(node: MetaProperty, name: Identifier): MetaProperty;
|
||||
createSatisfiesExpression(expression: Expression, type: TypeNode): SatisfiesExpression;
|
||||
updateSatisfiesExpression(node: SatisfiesExpression, expression: Expression, type: TypeNode): SatisfiesExpression;
|
||||
|
||||
//
|
||||
// Misc
|
||||
|
||||
@@ -1995,6 +1995,7 @@ namespace ts {
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
case SyntaxKind.AsExpression:
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
case SyntaxKind.NonNullExpression:
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
@@ -2095,6 +2096,8 @@ namespace ts {
|
||||
return (parent as ExpressionWithTypeArguments).expression === node && !isPartOfTypeNode(parent);
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
return (parent as ShorthandPropertyAssignment).objectAssignmentInitializer === node;
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
return node === (parent as SatisfiesExpression).expression;
|
||||
default:
|
||||
return isExpressionNode(parent);
|
||||
}
|
||||
@@ -3801,6 +3804,7 @@ namespace ts {
|
||||
return OperatorPrecedence.Member;
|
||||
|
||||
case SyntaxKind.AsExpression:
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
return OperatorPrecedence.Relational;
|
||||
|
||||
case SyntaxKind.ThisKeyword:
|
||||
@@ -3859,6 +3863,7 @@ namespace ts {
|
||||
case SyntaxKind.InstanceOfKeyword:
|
||||
case SyntaxKind.InKeyword:
|
||||
case SyntaxKind.AsKeyword:
|
||||
case SyntaxKind.SatisfiesKeyword:
|
||||
return OperatorPrecedence.Relational;
|
||||
case SyntaxKind.LessThanLessThanToken:
|
||||
case SyntaxKind.GreaterThanGreaterThanToken:
|
||||
@@ -5930,7 +5935,8 @@ namespace ts {
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.NonNullExpression:
|
||||
case SyntaxKind.PartiallyEmittedExpression:
|
||||
node = (node as CallExpression | PropertyAccessExpression | ElementAccessExpression | AsExpression | NonNullExpression | PartiallyEmittedExpression).expression;
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
node = (node as CallExpression | PropertyAccessExpression | ElementAccessExpression | AsExpression | NonNullExpression | PartiallyEmittedExpression | SatisfiesExpression).expression;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -1642,6 +1642,7 @@ namespace ts {
|
||||
case SyntaxKind.OmittedExpression:
|
||||
case SyntaxKind.CommaListExpression:
|
||||
case SyntaxKind.PartiallyEmittedExpression:
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
return true;
|
||||
default:
|
||||
return isUnaryExpressionKind(kind);
|
||||
|
||||
@@ -888,13 +888,19 @@ namespace ts {
|
||||
nodeVisitor(node.type, visitor, isTypeNode));
|
||||
},
|
||||
|
||||
[SyntaxKind.SatisfiesExpression]: function visitEachChildOfSatisfiesExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) {
|
||||
return context.factory.updateSatisfiesExpression(node,
|
||||
nodeVisitor(node.expression, visitor, isExpression),
|
||||
nodeVisitor(node.type, visitor, isTypeNode));
|
||||
},
|
||||
|
||||
[SyntaxKind.NonNullExpression]: function visitEachChildOfNonNullExpression(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) {
|
||||
return isOptionalChain(node) ?
|
||||
context.factory.updateNonNullChain(node,
|
||||
nodeVisitor(node.expression, visitor, isExpression)) :
|
||||
context.factory.updateNonNullExpression(node,
|
||||
nodeVisitor(node.expression, visitor, isExpression));
|
||||
},
|
||||
},
|
||||
|
||||
[SyntaxKind.MetaProperty]: function visitEachChildOfMetaProperty(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) {
|
||||
return context.factory.updateMetaProperty(node,
|
||||
|
||||
@@ -1388,6 +1388,7 @@ namespace FourSlashInterface {
|
||||
"package",
|
||||
"readonly",
|
||||
"return",
|
||||
"satisfies",
|
||||
"string",
|
||||
"super",
|
||||
"switch",
|
||||
@@ -1503,6 +1504,7 @@ namespace FourSlashInterface {
|
||||
"null",
|
||||
"package",
|
||||
"return",
|
||||
"satisfies",
|
||||
"super",
|
||||
"switch",
|
||||
"this",
|
||||
@@ -1601,6 +1603,7 @@ namespace FourSlashInterface {
|
||||
"package",
|
||||
"readonly",
|
||||
"return",
|
||||
"satisfies",
|
||||
"string",
|
||||
"super",
|
||||
"switch",
|
||||
@@ -1655,6 +1658,7 @@ namespace FourSlashInterface {
|
||||
"null",
|
||||
"package",
|
||||
"return",
|
||||
"satisfies",
|
||||
"super",
|
||||
"switch",
|
||||
"this",
|
||||
|
||||
@@ -449,6 +449,10 @@ namespace ts.CallHierarchy {
|
||||
recordCallSite(node as AccessExpression);
|
||||
forEachChild(node, collect);
|
||||
break;
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
// do not descend into the type side of an assertion
|
||||
collect((node as SatisfiesExpression).expression);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPartOfTypeNode(node)) {
|
||||
|
||||
@@ -369,6 +369,7 @@ namespace ts {
|
||||
case SyntaxKind.InstanceOfKeyword:
|
||||
case SyntaxKind.InKeyword:
|
||||
case SyntaxKind.AsKeyword:
|
||||
case SyntaxKind.SatisfiesKeyword:
|
||||
case SyntaxKind.EqualsEqualsToken:
|
||||
case SyntaxKind.ExclamationEqualsToken:
|
||||
case SyntaxKind.EqualsEqualsEqualsToken:
|
||||
|
||||
@@ -2675,6 +2675,9 @@ namespace ts.Completions {
|
||||
|
||||
case SyntaxKind.ExtendsKeyword:
|
||||
return parentKind === SyntaxKind.TypeParameter;
|
||||
|
||||
case SyntaxKind.SatisfiesKeyword:
|
||||
return parentKind === SyntaxKind.SatisfiesExpression;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -3962,6 +3965,7 @@ namespace ts.Completions {
|
||||
return kind === SyntaxKind.AsyncKeyword
|
||||
|| kind === SyntaxKind.AwaitKeyword
|
||||
|| kind === SyntaxKind.AsKeyword
|
||||
|| kind === SyntaxKind.SatisfiesKeyword
|
||||
|| kind === SyntaxKind.TypeKeyword
|
||||
|| !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind);
|
||||
}
|
||||
|
||||
@@ -449,6 +449,7 @@ namespace ts.formatting {
|
||||
case SyntaxKind.TypePredicate:
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.IntersectionType:
|
||||
case SyntaxKind.SatisfiesExpression:
|
||||
return true;
|
||||
|
||||
// equals in binding elements: function foo([[x, y] = [1, 2]])
|
||||
|
||||
@@ -143,6 +143,8 @@ namespace Harness {
|
||||
"exactOptionalPropertyTypes",
|
||||
"useDefineForClassFields",
|
||||
"useUnknownInCatchVariables",
|
||||
"noUncheckedIndexedAccess",
|
||||
"noPropertyAccessFromIndexSignature",
|
||||
];
|
||||
private fileName: string;
|
||||
private justName: string;
|
||||
|
||||
Reference in New Issue
Block a user