mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 21:36:50 -05:00
Merge pull request #26679 from Microsoft/improveGetTypeOfExpression
Improve control flow analysis of type assertions
This commit is contained in:
@@ -21699,15 +21699,19 @@ namespace ts {
|
||||
* to cache the result.
|
||||
*/
|
||||
function getTypeOfExpression(node: Expression, cache?: boolean) {
|
||||
const expr = skipParentheses(node);
|
||||
// Optimize for the common case of a call to a function with a single non-generic call
|
||||
// signature where we can just fetch the return type without checking the arguments.
|
||||
if (node.kind === SyntaxKind.CallExpression && (<CallExpression>node).expression.kind !== SyntaxKind.SuperKeyword && !isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true) && !isSymbolOrSymbolForCall(node)) {
|
||||
const funcType = checkNonNullExpression((<CallExpression>node).expression);
|
||||
if (expr.kind === SyntaxKind.CallExpression && (<CallExpression>expr).expression.kind !== SyntaxKind.SuperKeyword && !isRequireCall(expr, /*checkArgumentIsStringLiteralLike*/ true) && !isSymbolOrSymbolForCall(expr)) {
|
||||
const funcType = checkNonNullExpression((<CallExpression>expr).expression);
|
||||
const signature = getSingleCallSignature(funcType);
|
||||
if (signature && !signature.typeParameters) {
|
||||
return getReturnTypeOfSignature(signature);
|
||||
}
|
||||
}
|
||||
else if (expr.kind === SyntaxKind.TypeAssertionExpression || expr.kind === SyntaxKind.AsExpression) {
|
||||
return getTypeFromTypeNode((<TypeAssertion>expr).type);
|
||||
}
|
||||
// Otherwise simply call checkExpression. Ideally, the entire family of checkXXX functions
|
||||
// should have a parameter that indicates whether full error checking is required such that
|
||||
// we can perform the optimizations locally.
|
||||
|
||||
@@ -184,4 +184,24 @@ tests/cases/compiler/controlFlowSelfReferentialLoop.ts(17,29): error TS7006: Par
|
||||
b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
|
||||
}
|
||||
}
|
||||
export default md5;
|
||||
export default md5;
|
||||
|
||||
// Repro from #26655
|
||||
|
||||
interface DataShape {
|
||||
message: { id: string }
|
||||
}
|
||||
|
||||
function getObject(id: string | number) {
|
||||
return {} as any
|
||||
}
|
||||
|
||||
;(() => {
|
||||
let id: string | number = 'a'
|
||||
while (1) {
|
||||
const data = getObject(id) as DataShape
|
||||
const message = data.message
|
||||
id = message.id
|
||||
}
|
||||
})()
|
||||
|
||||
@@ -98,7 +98,27 @@ function md5(string:string): void {
|
||||
b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
|
||||
}
|
||||
}
|
||||
export default md5;
|
||||
export default md5;
|
||||
|
||||
// Repro from #26655
|
||||
|
||||
interface DataShape {
|
||||
message: { id: string }
|
||||
}
|
||||
|
||||
function getObject(id: string | number) {
|
||||
return {} as any
|
||||
}
|
||||
|
||||
;(() => {
|
||||
let id: string | number = 'a'
|
||||
while (1) {
|
||||
const data = getObject(id) as DataShape
|
||||
const message = data.message
|
||||
id = message.id
|
||||
}
|
||||
})()
|
||||
|
||||
|
||||
//// [controlFlowSelfReferentialLoop.js]
|
||||
"use strict";
|
||||
@@ -204,3 +224,15 @@ function md5(string) {
|
||||
}
|
||||
}
|
||||
exports["default"] = md5;
|
||||
function getObject(id) {
|
||||
return {};
|
||||
}
|
||||
;
|
||||
(function () {
|
||||
var id = 'a';
|
||||
while (1) {
|
||||
var data = getObject(id);
|
||||
var message = data.message;
|
||||
id = message.id;
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -831,3 +831,45 @@ function md5(string:string): void {
|
||||
export default md5;
|
||||
>md5 : Symbol(md5, Decl(controlFlowSelfReferentialLoop.ts, 0, 0))
|
||||
|
||||
// Repro from #26655
|
||||
|
||||
interface DataShape {
|
||||
>DataShape : Symbol(DataShape, Decl(controlFlowSelfReferentialLoop.ts, 99, 19))
|
||||
|
||||
message: { id: string }
|
||||
>message : Symbol(DataShape.message, Decl(controlFlowSelfReferentialLoop.ts, 103, 21))
|
||||
>id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 104, 12))
|
||||
}
|
||||
|
||||
function getObject(id: string | number) {
|
||||
>getObject : Symbol(getObject, Decl(controlFlowSelfReferentialLoop.ts, 105, 1))
|
||||
>id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 107, 19))
|
||||
|
||||
return {} as any
|
||||
}
|
||||
|
||||
;(() => {
|
||||
let id: string | number = 'a'
|
||||
>id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 112, 5))
|
||||
|
||||
while (1) {
|
||||
const data = getObject(id) as DataShape
|
||||
>data : Symbol(data, Decl(controlFlowSelfReferentialLoop.ts, 114, 9))
|
||||
>getObject : Symbol(getObject, Decl(controlFlowSelfReferentialLoop.ts, 105, 1))
|
||||
>id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 112, 5))
|
||||
>DataShape : Symbol(DataShape, Decl(controlFlowSelfReferentialLoop.ts, 99, 19))
|
||||
|
||||
const message = data.message
|
||||
>message : Symbol(message, Decl(controlFlowSelfReferentialLoop.ts, 115, 9))
|
||||
>data.message : Symbol(DataShape.message, Decl(controlFlowSelfReferentialLoop.ts, 103, 21))
|
||||
>data : Symbol(data, Decl(controlFlowSelfReferentialLoop.ts, 114, 9))
|
||||
>message : Symbol(DataShape.message, Decl(controlFlowSelfReferentialLoop.ts, 103, 21))
|
||||
|
||||
id = message.id
|
||||
>id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 112, 5))
|
||||
>message.id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 104, 12))
|
||||
>message : Symbol(message, Decl(controlFlowSelfReferentialLoop.ts, 115, 9))
|
||||
>id : Symbol(id, Decl(controlFlowSelfReferentialLoop.ts, 104, 12))
|
||||
}
|
||||
})()
|
||||
|
||||
|
||||
@@ -1260,3 +1260,54 @@ function md5(string:string): void {
|
||||
export default md5;
|
||||
>md5 : (string: string) => void
|
||||
|
||||
// Repro from #26655
|
||||
|
||||
interface DataShape {
|
||||
message: { id: string }
|
||||
>message : { id: string; }
|
||||
>id : string
|
||||
}
|
||||
|
||||
function getObject(id: string | number) {
|
||||
>getObject : (id: string | number) => any
|
||||
>id : string | number
|
||||
|
||||
return {} as any
|
||||
>{} as any : any
|
||||
>{} : {}
|
||||
}
|
||||
|
||||
;(() => {
|
||||
>(() => { let id: string | number = 'a' while (1) { const data = getObject(id) as DataShape const message = data.message id = message.id }})() : void
|
||||
>(() => { let id: string | number = 'a' while (1) { const data = getObject(id) as DataShape const message = data.message id = message.id }}) : () => void
|
||||
>() => { let id: string | number = 'a' while (1) { const data = getObject(id) as DataShape const message = data.message id = message.id }} : () => void
|
||||
|
||||
let id: string | number = 'a'
|
||||
>id : string | number
|
||||
>'a' : "a"
|
||||
|
||||
while (1) {
|
||||
>1 : 1
|
||||
|
||||
const data = getObject(id) as DataShape
|
||||
>data : DataShape
|
||||
>getObject(id) as DataShape : DataShape
|
||||
>getObject(id) : any
|
||||
>getObject : (id: string | number) => any
|
||||
>id : string
|
||||
|
||||
const message = data.message
|
||||
>message : { id: string; }
|
||||
>data.message : { id: string; }
|
||||
>data : DataShape
|
||||
>message : { id: string; }
|
||||
|
||||
id = message.id
|
||||
>id = message.id : string
|
||||
>id : string | number
|
||||
>message.id : string
|
||||
>message : { id: string; }
|
||||
>id : string
|
||||
}
|
||||
})()
|
||||
|
||||
|
||||
@@ -99,4 +99,23 @@ function md5(string:string): void {
|
||||
b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
|
||||
}
|
||||
}
|
||||
export default md5;
|
||||
export default md5;
|
||||
|
||||
// Repro from #26655
|
||||
|
||||
interface DataShape {
|
||||
message: { id: string }
|
||||
}
|
||||
|
||||
function getObject(id: string | number) {
|
||||
return {} as any
|
||||
}
|
||||
|
||||
;(() => {
|
||||
let id: string | number = 'a'
|
||||
while (1) {
|
||||
const data = getObject(id) as DataShape
|
||||
const message = data.message
|
||||
id = message.id
|
||||
}
|
||||
})()
|
||||
|
||||
Reference in New Issue
Block a user