mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-07 05:41:22 -06:00
In JS, constructor functions infer from call+construct (#28353)
* constructor functions infer from call+construct Also fix an incorrect combining of inferences for rest parameters: the inferred types will be arrays in the body of the function and the arguments from outside the function will be the element type. * All functions infer from call+construct contexts
This commit is contained in:
parent
1089424035
commit
ea8ccc2ce4
@ -283,6 +283,7 @@ namespace ts {
|
||||
getNumberType: () => numberType,
|
||||
createPromiseType,
|
||||
createArrayType,
|
||||
getElementTypeOfArrayType,
|
||||
getBooleanType: () => booleanType,
|
||||
getFalseType: (fresh?) => fresh ? falseType : regularFalseType,
|
||||
getTrueType: (fresh?) => fresh ? trueType : regularTrueType,
|
||||
@ -13222,6 +13223,10 @@ namespace ts {
|
||||
return !!(getObjectFlags(type) & ObjectFlags.Reference) && (<TypeReference>type).target === globalReadonlyArrayType;
|
||||
}
|
||||
|
||||
function getElementTypeOfArrayType(type: Type): Type | undefined {
|
||||
return isArrayType(type) && (type as TypeReference).typeArguments ? (type as TypeReference).typeArguments![0] : undefined;
|
||||
}
|
||||
|
||||
function isArrayLikeType(type: Type): boolean {
|
||||
// A type is array-like if it is a reference to the global Array or global ReadonlyArray type,
|
||||
// or if it is not the undefined or null type and if it is assignable to ReadonlyArray<any>
|
||||
|
||||
@ -3141,6 +3141,7 @@ namespace ts {
|
||||
/* @internal */ getNeverType(): Type;
|
||||
/* @internal */ getUnionType(types: Type[], subtypeReduction?: UnionReduction): Type;
|
||||
/* @internal */ createArrayType(elementType: Type): Type;
|
||||
/* @internal */ getElementTypeOfArrayType(arrayType: Type): Type | undefined;
|
||||
/* @internal */ createPromiseType(type: Type): Type;
|
||||
|
||||
/* @internal */ createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo | undefined, numberIndexInfo: IndexInfo | undefined): Type;
|
||||
|
||||
@ -413,10 +413,9 @@ namespace ts.codefix {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
inferTypeFromContext(reference, checker, usageContext);
|
||||
}
|
||||
const isConstructor = declaration.kind === SyntaxKind.Constructor;
|
||||
const callContexts = isConstructor ? usageContext.constructContexts : usageContext.callContexts;
|
||||
return callContexts && declaration.parameters.map((parameter, parameterIndex): ParameterInference => {
|
||||
const types: Type[] = [];
|
||||
const callContexts = [...usageContext.constructContexts || [], ...usageContext.callContexts || []];
|
||||
return declaration.parameters.map((parameter, parameterIndex): ParameterInference => {
|
||||
const types = [];
|
||||
const isRest = isRestParameter(parameter);
|
||||
let isOptional = false;
|
||||
for (const callContext of callContexts) {
|
||||
@ -434,7 +433,8 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
if (isIdentifier(parameter.name)) {
|
||||
types.push(...inferTypesFromReferences(getReferences(parameter.name, program, cancellationToken), checker, cancellationToken));
|
||||
const inferred = inferTypesFromReferences(getReferences(parameter.name, program, cancellationToken), checker, cancellationToken);
|
||||
types.push(...(isRest ? mapDefined(inferred, checker.getElementTypeOfArrayType) : inferred));
|
||||
}
|
||||
const type = unifyFromContext(types, checker);
|
||||
return {
|
||||
|
||||
27
tests/cases/fourslash/codeFixInferFromUsageConstructor.ts
Normal file
27
tests/cases/fourslash/codeFixInferFromUsageConstructor.ts
Normal file
@ -0,0 +1,27 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
// @strictNullChecks: true
|
||||
|
||||
////class TokenType {
|
||||
//// label;
|
||||
//// token;
|
||||
//// constructor([|label, token? |]) {
|
||||
//// this.label = label;
|
||||
//// this.token = token || "N/A";
|
||||
//// }
|
||||
////}
|
||||
////new TokenType("HI");
|
||||
verify.codeFix({
|
||||
description: "Infer parameter types from usage",
|
||||
index: 2,
|
||||
newFileContent:
|
||||
|
||||
`class TokenType {
|
||||
label;
|
||||
token;
|
||||
constructor(label: string, token?: string | undefined ) {
|
||||
this.label = label;
|
||||
this.token = token || "N/A";
|
||||
}
|
||||
}
|
||||
new TokenType("HI");`,
|
||||
});
|
||||
@ -0,0 +1,28 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @noImplicitAny: true
|
||||
// @Filename: test.js
|
||||
////function TokenType([|label, token |]) {
|
||||
//// this.label = label;
|
||||
//// this.token = token || "N/A";
|
||||
////};
|
||||
////new TokenType("HI")
|
||||
|
||||
verify.codeFix({
|
||||
description: "Infer parameter types from usage",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
|
||||
`/**
|
||||
* @param {string} label
|
||||
* @param {string} [token]
|
||||
*/
|
||||
function TokenType(label, token ) {
|
||||
this.label = label;
|
||||
this.token = token || "N/A";
|
||||
};
|
||||
new TokenType("HI")`,
|
||||
});
|
||||
|
||||
|
||||
@ -9,4 +9,4 @@
|
||||
////f(3, false, "s2");
|
||||
////f(4, "s1", "s2", false, "s4");
|
||||
|
||||
verify.rangeAfterCodeFix("...rest: (string | boolean)[]");
|
||||
verify.rangeAfterCodeFix("...rest: (string | boolean)[]");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user