Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
8 changes: 8 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -4724,5 +4724,13 @@
"Generate types for all packages without types": {
"category": "Message",
"code": 95068
},
"Add 'unknown' conversion for non-overlapping types": {
"category": "Message",
"code": 95069
},
"Add 'unknown' to all conversions of non-overlapping types": {
"category": "Message",
"code": 95070
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* @internal */
namespace ts.codefix {
const fixId = "addConvertToUnknownForNonOverlappingTypes";
const errorCodes = [Diagnostics.Conversion_of_type_0_to_type_1_may_be_a_mistake_because_neither_type_sufficiently_overlaps_with_the_other_If_this_was_intentional_convert_the_expression_to_unknown_first.code];
registerCodeFix({
errorCodes,
getCodeActions: (context) => {
const changes = textChanges.ChangeTracker.with(context, t => makeChange(t, context.sourceFile, context.span.start));
return [createCodeFixAction(fixId, changes, Diagnostics.Add_unknown_conversion_for_non_overlapping_types, fixId, Diagnostics.Add_unknown_to_all_conversions_of_non_overlapping_types)];
},
fixIds: [fixId],
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => makeChange(changes, diag.file, diag.start)),
});

function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number) {
const token = getTokenAtPosition(sourceFile, pos);

const asExpression = findAncestor<AsExpression>(token, isAsExpression)!;
if (!!asExpression) {
const nodeBeingConverted = asExpression.getChildAt(0);
const expressionBeingConverted = findAncestor<Expression>(nodeBeingConverted, isExpression)!;
Debug.assert(!!expressionBeingConverted, "Expected position to be owned by an expression.");

const replacement = createAsExpression(expressionBeingConverted, createKeywordTypeNode(SyntaxKind.UnknownKeyword));
changeTracker.replaceNode(sourceFile, expressionBeingConverted, replacement);
}

const typeAssertion = findAncestor<TypeAssertion>(token, isTypeAssertion)!;
if (!!typeAssertion) {
const nodeBeingConverted = typeAssertion.getLastToken();
const expressionBeingConverted = findAncestor<Expression>(nodeBeingConverted, isExpression)!;
Debug.assert(!!expressionBeingConverted, "Expected position to be owned by an expression.");

const replacement = createTypeAssertion(createKeywordTypeNode(SyntaxKind.UnknownKeyword), expressionBeingConverted);
changeTracker.replaceNode(sourceFile, expressionBeingConverted, replacement);
}
}
}
1 change: 1 addition & 0 deletions src/services/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"textChanges.ts",
"codeFixProvider.ts",
"refactorProvider.ts",
"codefixes/addConvertToUnknownForNonOverlappingTypes.ts",
"codefixes/addMissingInvocationForDecorator.ts",
"codefixes/annotateWithTypeFromJSDoc.ts",
"codefixes/convertFunctionToEs6Class.ts",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference path='fourslash.ts' />

////[|0 as string|]

verify.codeFix({
description: "Add 'unknown' conversion for non-overlapping types",
newRangeContent: `0 as unknown as string`
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference path='fourslash.ts' />

////[|0 * (4 + 3) / 100 as string|]

verify.codeFix({
description: "Add 'unknown' conversion for non-overlapping types",
newRangeContent: `0 * (4 + 3) / 100 as unknown as string`
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference path='fourslash.ts' />

////[|["words"] as string|]

verify.codeFix({
description: "Add 'unknown' conversion for non-overlapping types",
newRangeContent: `["words"] as unknown as string`
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference path='fourslash.ts' />

////[|"words" as object|]

verify.codeFix({
description: "Add 'unknown' conversion for non-overlapping types",
newRangeContent: `"words" as unknown as object`
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference path='fourslash.ts' />

////[|<string>0|]

verify.codeFix({
description: "Add 'unknown' conversion for non-overlapping types",
newRangeContent: `<string><unknown>0`
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference path='fourslash.ts' />

////[|<string>0 * (4 + 3) / 100|]

verify.codeFix({
description: "Add 'unknown' conversion for non-overlapping types",
newRangeContent: `<string><unknown>0 * (4 + 3) / 100`
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference path='fourslash.ts' />

////[|<string>["words"]|]

verify.codeFix({
description: "Add 'unknown' conversion for non-overlapping types",
newRangeContent: `<string><unknown>["words"]`
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference path='fourslash.ts' />

////[|<object>"words"|]

verify.codeFix({
description: "Add 'unknown' conversion for non-overlapping types",
newRangeContent: `<object><unknown>"words"`
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/// <reference path='fourslash.ts' />

////class C {
//// const s1 = 1 as string;
//// const o1 = s + " word" as object;
////
//// const s2 = <string>2;
//// const o2 = <object>s2;
////}

verify.codeFixAll({
fixId: "addConvertToUnknownForNonOverlappingTypes",
fixAllDescription: "Add 'unknown' to all conversions of non-overlapping types",
newFileContent:
`class C {
const s1 = 1 as unknown as string;
const o1 = s + " word" as unknown as object;

const s2 = <string><unknown>2;
const o2 = <object>s2;
}`
});