mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-25 12:40:05 -05:00
Reject return type inferences to the autoType or autoArrayType (#27169)
* Reject return type inferences to the autoType or autoArrayType * Accept new error positions
This commit is contained in:
@@ -13665,7 +13665,7 @@ namespace ts {
|
||||
// not contain anyFunctionType when we come back to this argument for its second round
|
||||
// of inference. Also, we exclude inferences for silentNeverType (which is used as a wildcard
|
||||
// when constructing types from type parameters that had no inference candidates).
|
||||
if (source.flags & TypeFlags.ContainsAnyFunctionType || source === silentNeverType) {
|
||||
if (source.flags & TypeFlags.ContainsAnyFunctionType || source === silentNeverType || (priority & InferencePriority.ReturnType && (source === autoType || source === autoArrayType))) {
|
||||
return;
|
||||
}
|
||||
const inference = getInferenceInfoForType(target);
|
||||
@@ -14904,7 +14904,7 @@ namespace ts {
|
||||
// we give type 'any[]' to 'x' instead of using the type determined by control flow analysis such that operations
|
||||
// on empty arrays are possible without implicit any errors and new element types can be inferred without
|
||||
// type mismatch errors.
|
||||
const resultType = getObjectFlags(evolvedType) & ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) ? anyArrayType : finalizeEvolvingArrayType(evolvedType);
|
||||
const resultType = getObjectFlags(evolvedType) & ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) ? autoArrayType : finalizeEvolvingArrayType(evolvedType);
|
||||
if (reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
|
||||
return declaredType;
|
||||
}
|
||||
@@ -15895,7 +15895,7 @@ namespace ts {
|
||||
// A variable is considered uninitialized when it is possible to analyze the entire control flow graph
|
||||
// from declaration to use, and when the variable's declared type doesn't include undefined but the
|
||||
// control flow based type does include undefined.
|
||||
if (type === autoType || type === autoArrayType) {
|
||||
if (!isEvolvingArrayOperationTarget(node) && (type === autoType || type === autoArrayType)) {
|
||||
if (flowType === autoType || flowType === autoArrayType) {
|
||||
if (noImplicitAny) {
|
||||
error(getNameOfDeclaration(declaration), Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined, symbolToString(symbol), typeToString(flowType));
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
tests/cases/compiler/inferenceShouldFailOnEvolvingArrays.ts(7,11): error TS2345: Argument of type '42' is not assignable to parameter of type 'string'.
|
||||
tests/cases/compiler/inferenceShouldFailOnEvolvingArrays.ts(9,15): error TS2345: Argument of type '42' is not assignable to parameter of type 'string'.
|
||||
tests/cases/compiler/inferenceShouldFailOnEvolvingArrays.ts(15,17): error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/compiler/inferenceShouldFailOnEvolvingArrays.ts(17,19): error TS2345: Argument of type '42' is not assignable to parameter of type 'string'.
|
||||
tests/cases/compiler/inferenceShouldFailOnEvolvingArrays.ts(18,22): error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/inferenceShouldFailOnEvolvingArrays.ts (5 errors) ====
|
||||
// repro from https://github.com/Microsoft/TypeScript/issues/25675
|
||||
// The type of `arg` blocks inference but simplifies to T.
|
||||
function logLength<T extends string, U extends string>(arg: { [K in U]: T }[U]): T {
|
||||
console.log(arg.length);
|
||||
return arg;
|
||||
}
|
||||
logLength(42); // error
|
||||
~~
|
||||
!!! error TS2345: Argument of type '42' is not assignable to parameter of type 'string'.
|
||||
let z;
|
||||
z = logLength(42); // no error; T is inferred as `any`
|
||||
~~
|
||||
!!! error TS2345: Argument of type '42' is not assignable to parameter of type 'string'.
|
||||
|
||||
function logFirstLength<T extends string[], U extends string>(arg: { [K in U]: T }[U]): T {
|
||||
console.log(arg[0].length);
|
||||
return arg;
|
||||
}
|
||||
logFirstLength([42]); // error
|
||||
~~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
let zz = [];
|
||||
zz.push(logLength(42)); // no error; T is inferred as `any`
|
||||
~~
|
||||
!!! error TS2345: Argument of type '42' is not assignable to parameter of type 'string'.
|
||||
zz = logFirstLength([42]); // no error; T is inferred as `any[]`
|
||||
~~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
@@ -0,0 +1,39 @@
|
||||
//// [inferenceShouldFailOnEvolvingArrays.ts]
|
||||
// repro from https://github.com/Microsoft/TypeScript/issues/25675
|
||||
// The type of `arg` blocks inference but simplifies to T.
|
||||
function logLength<T extends string, U extends string>(arg: { [K in U]: T }[U]): T {
|
||||
console.log(arg.length);
|
||||
return arg;
|
||||
}
|
||||
logLength(42); // error
|
||||
let z;
|
||||
z = logLength(42); // no error; T is inferred as `any`
|
||||
|
||||
function logFirstLength<T extends string[], U extends string>(arg: { [K in U]: T }[U]): T {
|
||||
console.log(arg[0].length);
|
||||
return arg;
|
||||
}
|
||||
logFirstLength([42]); // error
|
||||
let zz = [];
|
||||
zz.push(logLength(42)); // no error; T is inferred as `any`
|
||||
zz = logFirstLength([42]); // no error; T is inferred as `any[]`
|
||||
|
||||
//// [inferenceShouldFailOnEvolvingArrays.js]
|
||||
"use strict";
|
||||
// repro from https://github.com/Microsoft/TypeScript/issues/25675
|
||||
// The type of `arg` blocks inference but simplifies to T.
|
||||
function logLength(arg) {
|
||||
console.log(arg.length);
|
||||
return arg;
|
||||
}
|
||||
logLength(42); // error
|
||||
var z;
|
||||
z = logLength(42); // no error; T is inferred as `any`
|
||||
function logFirstLength(arg) {
|
||||
console.log(arg[0].length);
|
||||
return arg;
|
||||
}
|
||||
logFirstLength([42]); // error
|
||||
var zz = [];
|
||||
zz.push(logLength(42)); // no error; T is inferred as `any`
|
||||
zz = logFirstLength([42]); // no error; T is inferred as `any[]`
|
||||
@@ -0,0 +1,73 @@
|
||||
=== tests/cases/compiler/inferenceShouldFailOnEvolvingArrays.ts ===
|
||||
// repro from https://github.com/Microsoft/TypeScript/issues/25675
|
||||
// The type of `arg` blocks inference but simplifies to T.
|
||||
function logLength<T extends string, U extends string>(arg: { [K in U]: T }[U]): T {
|
||||
>logLength : Symbol(logLength, Decl(inferenceShouldFailOnEvolvingArrays.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferenceShouldFailOnEvolvingArrays.ts, 2, 19))
|
||||
>U : Symbol(U, Decl(inferenceShouldFailOnEvolvingArrays.ts, 2, 36))
|
||||
>arg : Symbol(arg, Decl(inferenceShouldFailOnEvolvingArrays.ts, 2, 55))
|
||||
>K : Symbol(K, Decl(inferenceShouldFailOnEvolvingArrays.ts, 2, 63))
|
||||
>U : Symbol(U, Decl(inferenceShouldFailOnEvolvingArrays.ts, 2, 36))
|
||||
>T : Symbol(T, Decl(inferenceShouldFailOnEvolvingArrays.ts, 2, 19))
|
||||
>U : Symbol(U, Decl(inferenceShouldFailOnEvolvingArrays.ts, 2, 36))
|
||||
>T : Symbol(T, Decl(inferenceShouldFailOnEvolvingArrays.ts, 2, 19))
|
||||
|
||||
console.log(arg.length);
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>arg.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
|
||||
>arg : Symbol(arg, Decl(inferenceShouldFailOnEvolvingArrays.ts, 2, 55))
|
||||
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
return arg;
|
||||
>arg : Symbol(arg, Decl(inferenceShouldFailOnEvolvingArrays.ts, 2, 55))
|
||||
}
|
||||
logLength(42); // error
|
||||
>logLength : Symbol(logLength, Decl(inferenceShouldFailOnEvolvingArrays.ts, 0, 0))
|
||||
|
||||
let z;
|
||||
>z : Symbol(z, Decl(inferenceShouldFailOnEvolvingArrays.ts, 7, 3))
|
||||
|
||||
z = logLength(42); // no error; T is inferred as `any`
|
||||
>z : Symbol(z, Decl(inferenceShouldFailOnEvolvingArrays.ts, 7, 3))
|
||||
>logLength : Symbol(logLength, Decl(inferenceShouldFailOnEvolvingArrays.ts, 0, 0))
|
||||
|
||||
function logFirstLength<T extends string[], U extends string>(arg: { [K in U]: T }[U]): T {
|
||||
>logFirstLength : Symbol(logFirstLength, Decl(inferenceShouldFailOnEvolvingArrays.ts, 8, 18))
|
||||
>T : Symbol(T, Decl(inferenceShouldFailOnEvolvingArrays.ts, 10, 24))
|
||||
>U : Symbol(U, Decl(inferenceShouldFailOnEvolvingArrays.ts, 10, 43))
|
||||
>arg : Symbol(arg, Decl(inferenceShouldFailOnEvolvingArrays.ts, 10, 62))
|
||||
>K : Symbol(K, Decl(inferenceShouldFailOnEvolvingArrays.ts, 10, 70))
|
||||
>U : Symbol(U, Decl(inferenceShouldFailOnEvolvingArrays.ts, 10, 43))
|
||||
>T : Symbol(T, Decl(inferenceShouldFailOnEvolvingArrays.ts, 10, 24))
|
||||
>U : Symbol(U, Decl(inferenceShouldFailOnEvolvingArrays.ts, 10, 43))
|
||||
>T : Symbol(T, Decl(inferenceShouldFailOnEvolvingArrays.ts, 10, 24))
|
||||
|
||||
console.log(arg[0].length);
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>arg[0].length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
|
||||
>arg : Symbol(arg, Decl(inferenceShouldFailOnEvolvingArrays.ts, 10, 62))
|
||||
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
return arg;
|
||||
>arg : Symbol(arg, Decl(inferenceShouldFailOnEvolvingArrays.ts, 10, 62))
|
||||
}
|
||||
logFirstLength([42]); // error
|
||||
>logFirstLength : Symbol(logFirstLength, Decl(inferenceShouldFailOnEvolvingArrays.ts, 8, 18))
|
||||
|
||||
let zz = [];
|
||||
>zz : Symbol(zz, Decl(inferenceShouldFailOnEvolvingArrays.ts, 15, 3))
|
||||
|
||||
zz.push(logLength(42)); // no error; T is inferred as `any`
|
||||
>zz.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
|
||||
>zz : Symbol(zz, Decl(inferenceShouldFailOnEvolvingArrays.ts, 15, 3))
|
||||
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
|
||||
>logLength : Symbol(logLength, Decl(inferenceShouldFailOnEvolvingArrays.ts, 0, 0))
|
||||
|
||||
zz = logFirstLength([42]); // no error; T is inferred as `any[]`
|
||||
>zz : Symbol(zz, Decl(inferenceShouldFailOnEvolvingArrays.ts, 15, 3))
|
||||
>logFirstLength : Symbol(logFirstLength, Decl(inferenceShouldFailOnEvolvingArrays.ts, 8, 18))
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
=== tests/cases/compiler/inferenceShouldFailOnEvolvingArrays.ts ===
|
||||
// repro from https://github.com/Microsoft/TypeScript/issues/25675
|
||||
// The type of `arg` blocks inference but simplifies to T.
|
||||
function logLength<T extends string, U extends string>(arg: { [K in U]: T }[U]): T {
|
||||
>logLength : <T extends string, U extends string>(arg: { [K in U]: T; }[U]) => T
|
||||
>arg : { [K in U]: T; }[U]
|
||||
|
||||
console.log(arg.length);
|
||||
>console.log(arg.length) : void
|
||||
>console.log : (message?: any, ...optionalParams: any[]) => void
|
||||
>console : Console
|
||||
>log : (message?: any, ...optionalParams: any[]) => void
|
||||
>arg.length : number
|
||||
>arg : { [K in U]: T; }[U]
|
||||
>length : number
|
||||
|
||||
return arg;
|
||||
>arg : { [K in U]: T; }[U]
|
||||
}
|
||||
logLength(42); // error
|
||||
>logLength(42) : any
|
||||
>logLength : <T extends string, U extends string>(arg: { [K in U]: T; }[U]) => T
|
||||
>42 : 42
|
||||
|
||||
let z;
|
||||
>z : any
|
||||
|
||||
z = logLength(42); // no error; T is inferred as `any`
|
||||
>z = logLength(42) : any
|
||||
>z : any
|
||||
>logLength(42) : any
|
||||
>logLength : <T extends string, U extends string>(arg: { [K in U]: T; }[U]) => T
|
||||
>42 : 42
|
||||
|
||||
function logFirstLength<T extends string[], U extends string>(arg: { [K in U]: T }[U]): T {
|
||||
>logFirstLength : <T extends string[], U extends string>(arg: { [K in U]: T; }[U]) => T
|
||||
>arg : { [K in U]: T; }[U]
|
||||
|
||||
console.log(arg[0].length);
|
||||
>console.log(arg[0].length) : void
|
||||
>console.log : (message?: any, ...optionalParams: any[]) => void
|
||||
>console : Console
|
||||
>log : (message?: any, ...optionalParams: any[]) => void
|
||||
>arg[0].length : number
|
||||
>arg[0] : string
|
||||
>arg : { [K in U]: T; }[U]
|
||||
>0 : 0
|
||||
>length : number
|
||||
|
||||
return arg;
|
||||
>arg : { [K in U]: T; }[U]
|
||||
}
|
||||
logFirstLength([42]); // error
|
||||
>logFirstLength([42]) : any
|
||||
>logFirstLength : <T extends string[], U extends string>(arg: { [K in U]: T; }[U]) => T
|
||||
>[42] : number[]
|
||||
>42 : 42
|
||||
|
||||
let zz = [];
|
||||
>zz : any[]
|
||||
>[] : never[]
|
||||
|
||||
zz.push(logLength(42)); // no error; T is inferred as `any`
|
||||
>zz.push(logLength(42)) : number
|
||||
>zz.push : (...items: any[]) => number
|
||||
>zz : any[]
|
||||
>push : (...items: any[]) => number
|
||||
>logLength(42) : any
|
||||
>logLength : <T extends string, U extends string>(arg: { [K in U]: T; }[U]) => T
|
||||
>42 : 42
|
||||
|
||||
zz = logFirstLength([42]); // no error; T is inferred as `any[]`
|
||||
>zz = logFirstLength([42]) : any
|
||||
>zz : any[]
|
||||
>logFirstLength([42]) : any
|
||||
>logFirstLength : <T extends string[], U extends string>(arg: { [K in U]: T; }[U]) => T
|
||||
>[42] : number[]
|
||||
>42 : 42
|
||||
|
||||
19
tests/cases/compiler/inferenceShouldFailOnEvolvingArrays.ts
Normal file
19
tests/cases/compiler/inferenceShouldFailOnEvolvingArrays.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
// @strict: true
|
||||
// repro from https://github.com/Microsoft/TypeScript/issues/25675
|
||||
// The type of `arg` blocks inference but simplifies to T.
|
||||
function logLength<T extends string, U extends string>(arg: { [K in U]: T }[U]): T {
|
||||
console.log(arg.length);
|
||||
return arg;
|
||||
}
|
||||
logLength(42); // error
|
||||
let z;
|
||||
z = logLength(42); // no error; T is inferred as `any`
|
||||
|
||||
function logFirstLength<T extends string[], U extends string>(arg: { [K in U]: T }[U]): T {
|
||||
console.log(arg[0].length);
|
||||
return arg;
|
||||
}
|
||||
logFirstLength([42]); // error
|
||||
let zz = [];
|
||||
zz.push(logLength(42)); // no error; T is inferred as `any`
|
||||
zz = logFirstLength([42]); // no error; T is inferred as `any[]`
|
||||
Reference in New Issue
Block a user