Merge branch 'master' into disallow-global-umd-merges

This commit is contained in:
Nathan Shively-Sanders 2019-10-25 09:53:48 -07:00
commit 98df06dde8
79 changed files with 3876 additions and 363 deletions

37
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,37 @@
name: CI
on:
push:
branches:
- master
- release-*
pull_request:
branches:
- master
- release-*
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [8.x, 10.x, 12.x]
steps:
- uses: actions/checkout@v1
with:
fetch-depth: 5
- name: Use node version ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Remove existing TypeScript
run: |
npm uninstall typescript --no-save
npm uninstall tslint --no-save
- name: npm install and test
run: |
npm install
npm update
npm test

View file

@ -1,5 +1,17 @@
// Rename this file 'launch.json' or merge its
// contents into your existing configurations.
/*
Copy this file into '.vscode/launch.json' or merge its
contents into your existing configurations.
If you want to remove the errors in comments for all JSON
files, add this to your settings in ~/.vscode/User/settings.json
"files.associations": {
"*.json": "jsonc"
},
*/
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
@ -10,7 +22,7 @@
"type": "node",
"protocol": "inspector",
"request": "launch",
"name": "Mocha Tests (currently opened test)",
"name": "Mocha Tests (currently opened test)",
"runtimeArgs": ["--nolazy"],
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
"args": [
@ -20,6 +32,8 @@
"--colors",
"built/local/run.js",
"-f",
// You can change this to be the name of a specific test file (without the file extension)
// to consistently launch the same test
"${fileBasenameNoExtension}",
"--skip-percent",
"0"
@ -34,6 +48,13 @@
"outFiles": [
"${workspaceRoot}/built/local/run.js"
]
},
{
// See: https://github.com/microsoft/TypeScript/wiki/Debugging-Language-Service-in-VS-Code
"type": "node",
"request": "attach",
"name": "Attach to VS Code TS Server via Port",
"processId": "${command:PickProcess}"
}
]
}
}

View file

@ -59,11 +59,11 @@ Run `gulp` to build a version of the compiler/language service that reflects cha
## Contributing bug fixes
TypeScript is currently accepting contributions in the form of bug fixes. A bug must have an issue tracking it in the issue tracker that has been approved (labelled ["help wanted"](https://github.com/Microsoft/TypeScript/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)) by the TypeScript team. Your pull request should include a link to the bug that you are fixing. If you've submitted a PR for a bug, please post a comment in the bug to avoid duplication of effort.
TypeScript is currently accepting contributions in the form of bug fixes. A bug must have an issue tracking it in the issue tracker that has been approved (labelled ["help wanted"](https://github.com/Microsoft/TypeScript/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) or in the "Backlog milestone") by the TypeScript team. Your pull request should include a link to the bug that you are fixing. If you've submitted a PR for a bug, please post a comment in the bug to avoid duplication of effort.
## Contributing features
Features (things that add new or improved functionality to TypeScript) may be accepted, but will need to first be approved ([labelled "help wanted"](https://github.com/Microsoft/TypeScript/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) by a TypeScript project maintainer) in the suggestion issue. Features with language design impact, or that are adequately satisfied with external tools, will not be accepted.
Features (things that add new or improved functionality to TypeScript) may be accepted, but will need to first be approved ([labelled "help wanted"](https://github.com/Microsoft/TypeScript/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22 or in the "Backlog" milestone) by a TypeScript project maintainer) in the suggestion issue. Features with language design impact, or that are adequately satisfied with external tools, will not be accepted.
Design changes will not be accepted at this time. If you have a design change proposal, please log a suggestion issue.

View file

@ -1,16 +1,15 @@
# TypeScript
[![Join the chat at https://gitter.im/microsoft/TypeScript](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/microsoft/TypeScript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/microsoft/TypeScript.svg?branch=master)](https://travis-ci.org/microsoft/TypeScript)
[![VSTS Build Status](https://dev.azure.com/typescript/TypeScript/_apis/build/status/Typescript/node10)](https://dev.azure.com/typescript/TypeScript/_build/latest?definitionId=4&view=logs)
[![npm version](https://badge.fury.io/js/typescript.svg)](https://www.npmjs.com/package/typescript)
[![Downloads](https://img.shields.io/npm/dm/typescript.svg)](https://www.npmjs.com/package/typescript)
[TypeScript](https://www.typescriptlang.org/) is a language for application-scale JavaScript. TypeScript adds optional types to JavaScript that support tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript compiles to readable, standards-based JavaScript. Try it out at the [playground](https://www.typescriptlang.org/play/), and stay up to date via [our blog](https://blogs.msdn.microsoft.com/typescript) and [Twitter account](https://twitter.com/typescript).
Find others who are using TypeScript at [our community page](https://www.typescriptlang.org/community/).
## Installing
For the latest stable version:
@ -31,6 +30,7 @@ There are many ways to [contribute](https://github.com/microsoft/TypeScript/blob
* [Submit bugs](https://github.com/microsoft/TypeScript/issues) and help us verify fixes as they are checked in.
* Review the [source code changes](https://github.com/microsoft/TypeScript/pulls).
* Engage with other TypeScript users and developers on [StackOverflow](https://stackoverflow.com/questions/tagged/typescript).
* Help each other in the [TypeScript Community Discord](https://discord.gg/typescript).
* Join the [#typescript](https://twitter.com/search?q=%23TypeScript) discussion on Twitter.
* [Contribute bug fixes](https://github.com/microsoft/TypeScript/blob/master/CONTRIBUTING.md).
* Read the language specification ([docx](https://github.com/microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.docx?raw=true),

View file

@ -2,7 +2,7 @@
"name": "typescript",
"author": "Microsoft Corp.",
"homepage": "https://www.typescriptlang.org/",
"version": "3.7.0",
"version": "3.8.0",
"license": "Apache-2.0",
"description": "TypeScript is a language for application scale JavaScript development",
"keywords": [

View file

@ -1,3 +1,4 @@
/* @internal */
namespace ts {
export const enum ModuleInstanceState {
@ -821,9 +822,6 @@ namespace ts {
case SyntaxKind.JSDocEnumTag:
bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag);
break;
case SyntaxKind.JSDocClassTag:
bindJSDocClassTag(node as JSDocClassTag);
break;
// In source files and blocks, bind functions first to match hoisting that occurs at runtime
case SyntaxKind.SourceFile: {
bindEachFunctionsFirst((node as SourceFile).statements);
@ -954,11 +952,10 @@ namespace ts {
if (!expression) {
return flags & FlowFlags.TrueCondition ? antecedent : unreachableFlow;
}
if (expression.kind === SyntaxKind.TrueKeyword && flags & FlowFlags.FalseCondition ||
expression.kind === SyntaxKind.FalseKeyword && flags & FlowFlags.TrueCondition) {
if (!isOptionalChainRoot(expression.parent)) {
return unreachableFlow;
}
if ((expression.kind === SyntaxKind.TrueKeyword && flags & FlowFlags.FalseCondition ||
expression.kind === SyntaxKind.FalseKeyword && flags & FlowFlags.TrueCondition) &&
!isExpressionOfOptionalChainRoot(expression) && !isNullishCoalesce(expression.parent)) {
return unreachableFlow;
}
if (!isNarrowingExpression(expression)) {
return antecedent;
@ -2006,7 +2003,12 @@ namespace ts {
switch (getAssignmentDeclarationPropertyAccessKind(declName.parent)) {
case AssignmentDeclarationKind.ExportsProperty:
case AssignmentDeclarationKind.ModuleExports:
container = file;
if (!isExternalOrCommonJsModule(file)) {
container = undefined!;
}
else {
container = file;
}
break;
case AssignmentDeclarationKind.ThisProperty:
container = declName.parent.expression;
@ -2020,7 +2022,9 @@ namespace ts {
case AssignmentDeclarationKind.None:
return Debug.fail("Shouldn't have detected typedef or enum on non-assignment declaration");
}
declareModuleMember(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
if (container) {
declareModuleMember(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
}
container = oldContainer;
}
}
@ -2454,6 +2458,8 @@ namespace ts {
case SyntaxKind.JSDocTypeLiteral:
case SyntaxKind.MappedType:
return bindAnonymousTypeWorker(node as TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral);
case SyntaxKind.JSDocClassTag:
return bindJSDocClassTag(node as JSDocClassTag);
case SyntaxKind.ObjectLiteralExpression:
return bindObjectLiteralExpression(<ObjectLiteralExpression>node);
case SyntaxKind.FunctionExpression:
@ -2691,7 +2697,8 @@ namespace ts {
const flags = exportAssignmentIsAlias(node)
? SymbolFlags.Alias // An export= with an EntityNameExpression or a ClassExpression exports all meanings of that identifier or class
: SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule;
declareSymbol(file.symbol.exports!, file.symbol, node, flags | SymbolFlags.Assignment, SymbolFlags.None);
const symbol = declareSymbol(file.symbol.exports!, file.symbol, node, flags | SymbolFlags.Assignment, SymbolFlags.None);
setValueDeclaration(symbol, node);
}
function bindThisPropertyAssignment(node: BindablePropertyAssignmentExpression | PropertyAccessExpression | LiteralLikeElementAccessExpression) {
@ -2709,7 +2716,7 @@ namespace ts {
}
}
if (constructorSymbol) {
if (constructorSymbol && constructorSymbol.valueDeclaration) {
// Declare a 'member' if the container is an ES5 class or ES6 constructor
constructorSymbol.members = constructorSymbol.members || createSymbolTable();
// It's acceptable for multiple 'this' assignments of the same identifier to occur
@ -2789,6 +2796,10 @@ namespace ts {
function bindObjectDefinePrototypeProperty(node: BindableObjectDefinePropertyCall) {
const namespaceSymbol = lookupSymbolForPropertyAccess((node.arguments[0] as PropertyAccessExpression).expression as EntityNameExpression);
if (namespaceSymbol) {
// Ensure the namespace symbol becomes class-like
addDeclarationToSymbol(namespaceSymbol, namespaceSymbol.valueDeclaration, SymbolFlags.Class);
}
bindPotentiallyNewExpandoMemberToNamespace(node, namespaceSymbol, /*isPrototypeProperty*/ true);
}

View file

@ -327,10 +327,6 @@ namespace ts {
/** This will be set during calls to `getResolvedSignature` where services determines an apparent number of arguments greater than what is actually provided. */
let apparentArgumentCount: number | undefined;
// This object is reused for `checkOptionalExpression` return values to avoid frequent GC due to nursery object allocations.
// This object represents a pool-size of 1.
const pooledOptionalTypeResult: { isOptional: boolean, type: Type } = { isOptional: false, type: undefined! };
// for public members that accept a Node or one of its subtypes, we must guard against
// synthetic nodes created during transformations by calling `getParseTreeNode`.
// for most of these, we perform the guard only on `checker` to avoid any possible
@ -712,10 +708,10 @@ namespace ts {
const noTypePredicate = createTypePredicate(TypePredicateKind.Identifier, "<<unresolved>>", 0, anyType);
const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, errorType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, errorType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
@ -2633,7 +2629,12 @@ namespace ts {
return undefined;
}
const init = isVariableDeclaration(decl) ? getDeclaredExpandoInitializer(decl) : getAssignedExpandoInitializer(decl);
return init && getSymbolOfNode(init) || undefined;
if (init) {
const initSymbol = getSymbolOfNode(init);
if (initSymbol) {
return mergeJSSymbols(initSymbol, symbol);
}
}
}
@ -4091,8 +4092,6 @@ namespace ts {
else if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral &&
type.symbol.valueDeclaration &&
isClassLike(type.symbol.valueDeclaration) &&
// Use `import` types for refs to other scopes, only anonymize something defined in the same scope
findAncestor(type.symbol.valueDeclaration, d => d === getSourceFileOfNode(context.enclosingDeclaration)) &&
!isValueSymbolAccessible(type.symbol, context.enclosingDeclaration)
) {
return createAnonymousTypeNode(type);
@ -7680,6 +7679,7 @@ namespace ts {
// The outer type parameters are those defined by enclosing generic classes, methods, or functions.
function getOuterTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] | undefined {
const declaration = symbol.flags & SymbolFlags.Class ? symbol.valueDeclaration : getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration)!;
Debug.assert(!!declaration, "Class was missing valueDeclaration -OR- non-class had no interface declarations");
return getOuterTypeParameters(declaration);
}
@ -7712,7 +7712,7 @@ namespace ts {
const signatures = getSignaturesOfType(type, SignatureKind.Construct);
if (signatures.length === 1) {
const s = signatures[0];
return !s.typeParameters && s.parameters.length === 1 && s.hasRestParameter && getElementTypeOfArrayType(getTypeOfParameter(s.parameters[0])) === anyType;
return !s.typeParameters && s.parameters.length === 1 && signatureHasRestParameter(s) && getElementTypeOfArrayType(getTypeOfParameter(s.parameters[0])) === anyType;
}
return false;
}
@ -8603,10 +8603,9 @@ namespace ts {
resolvedReturnType: Type | undefined,
resolvedTypePredicate: TypePredicate | undefined,
minArgumentCount: number,
hasRestParameter: boolean,
hasLiteralTypes: boolean,
flags: SignatureFlags
): Signature {
const sig = new Signature(checker);
const sig = new Signature(checker, flags);
sig.declaration = declaration;
sig.typeParameters = typeParameters;
sig.parameters = parameters;
@ -8614,8 +8613,6 @@ namespace ts {
sig.resolvedReturnType = resolvedReturnType;
sig.resolvedTypePredicate = resolvedTypePredicate;
sig.minArgumentCount = minArgumentCount;
sig.hasRestParameter = hasRestParameter;
sig.hasLiteralTypes = hasLiteralTypes;
sig.target = undefined;
sig.mapper = undefined;
return sig;
@ -8623,7 +8620,7 @@ namespace ts {
function cloneSignature(sig: Signature): Signature {
const result = createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, /*resolvedReturnType*/ undefined,
/*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.hasRestParameter, sig.hasLiteralTypes);
/*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.flags & SignatureFlags.PropagatingFlags);
result.target = sig.target;
result.mapper = sig.mapper;
return result;
@ -8637,14 +8634,19 @@ namespace ts {
return result;
}
function getOptionalCallSignature(signature: Signature) {
return signatureIsOptionalCall(signature) ? signature :
(signature.optionalCallSignatureCache || (signature.optionalCallSignatureCache = createOptionalCallSignature(signature)));
}
function createOptionalCallSignature(signature: Signature) {
const result = cloneSignature(signature);
result.isOptionalCall = true;
result.flags |= SignatureFlags.IsOptionalCall;
return result;
}
function getExpandedParameters(sig: Signature): readonly Symbol[] {
if (sig.hasRestParameter) {
if (signatureHasRestParameter(sig)) {
const restIndex = sig.parameters.length - 1;
const restParameter = sig.parameters[restIndex];
const restType = getTypeOfSymbol(restParameter);
@ -8670,7 +8672,7 @@ namespace ts {
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
if (baseSignatures.length === 0) {
return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false)];
return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None)];
}
const baseTypeNode = getBaseTypeNodeOfClass(classType)!;
const isJavaScript = isInJSFile(baseTypeNode);
@ -8834,8 +8836,6 @@ namespace ts {
const params = combineUnionParameters(left, right);
const thisParam = combineUnionThisParam(left.thisParameter, right.thisParameter);
const minArgCount = Math.max(left.minArgumentCount, right.minArgumentCount);
const hasRestParam = left.hasRestParameter || right.hasRestParameter;
const hasLiteralTypes = left.hasLiteralTypes || right.hasLiteralTypes;
const result = createSignature(
declaration,
left.typeParameters || right.typeParameters,
@ -8844,8 +8844,7 @@ namespace ts {
/*resolvedReturnType*/ undefined,
/*resolvedTypePredicate*/ undefined,
minArgCount,
hasRestParam,
hasLiteralTypes
(left.flags | right.flags) & SignatureFlags.PropagatingFlags
);
result.unionSignatures = concatenate(left.unionSignatures || [left], [right]);
return result;
@ -9027,7 +9026,7 @@ namespace ts {
constructSignatures = addRange(constructSignatures.slice(), mapDefined(
type.callSignatures,
sig => isJSConstructor(sig.declaration) ?
createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, classType, /*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.hasRestParameter, sig.hasLiteralTypes) :
createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, classType, /*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.flags & SignatureFlags.PropagatingFlags) :
undefined));
}
if (!constructSignatures.length) {
@ -10034,7 +10033,7 @@ namespace ts {
const links = getNodeLinks(declaration);
if (!links.resolvedSignature) {
const parameters: Symbol[] = [];
let hasLiteralTypes = false;
let flags = SignatureFlags.None;
let minArgumentCount = 0;
let thisParameter: Symbol | undefined;
let hasThisParameter = false;
@ -10068,7 +10067,7 @@ namespace ts {
}
if (type && type.kind === SyntaxKind.LiteralType) {
hasLiteralTypes = true;
flags |= SignatureFlags.HasLiteralTypes;
}
// Record a new minimum argument count if this is not an optional parameter
@ -10097,10 +10096,12 @@ namespace ts {
getDeclaredTypeOfClassOrInterface(getMergedSymbol((<ClassDeclaration>declaration.parent).symbol))
: undefined;
const typeParameters = classType ? classType.localTypeParameters : getTypeParametersFromDeclaration(declaration);
const hasRestLikeParameter = hasRestParameter(declaration) || isInJSFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters);
if (hasRestParameter(declaration) || isInJSFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters)) {
flags |= SignatureFlags.HasRestParameter;
}
links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters,
/*resolvedReturnType*/ undefined, /*resolvedTypePredicate*/ undefined,
minArgumentCount, hasRestLikeParameter, hasLiteralTypes);
minArgumentCount, flags);
}
return links.resolvedSignature;
}
@ -10255,8 +10256,8 @@ namespace ts {
signature.unionSignatures ? getUnionType(map(signature.unionSignatures, getReturnTypeOfSignature), UnionReduction.Subtype) :
getReturnTypeFromAnnotation(signature.declaration!) ||
(nodeIsMissing((<FunctionLikeDeclaration>signature.declaration).body) ? anyType : getReturnTypeFromBody(<FunctionLikeDeclaration>signature.declaration));
if (signature.isOptionalCall) {
type = propagateOptionalTypeMarker(type, /*wasOptional*/ true);
if (signatureIsOptionalCall(signature)) {
type = addOptionalTypeMarker(type);
}
if (!popTypeResolution()) {
if (signature.declaration) {
@ -10316,7 +10317,7 @@ namespace ts {
}
function tryGetRestTypeOfSignature(signature: Signature): Type | undefined {
if (signature.hasRestParameter) {
if (signatureHasRestParameter(signature)) {
const sigRestType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
const restType = isTupleType(sigRestType) ? getRestTypeOfTupleType(sigRestType) : sigRestType;
return restType && getIndexTypeOfType(restType, IndexKind.Number);
@ -10748,7 +10749,7 @@ namespace ts {
/**
* A JSdoc TypeReference may be to a value, but resolve it as a type anyway.
* Note: If the value is imported from commonjs, it should really be an alias,
* but this function fakes special-case code fakes alias resolution as well.
* but this function's special-case code fakes alias resolution as well.
*/
function getTypeFromJSDocValueReference(node: NodeWithTypeArguments, symbol: Symbol): Type | undefined {
const valueType = getTypeOfSymbol(symbol);
@ -10760,7 +10761,7 @@ namespace ts {
&& isCallExpression(decl.initializer)
&& isRequireCall(decl.initializer, /*requireStringLiteralLikeArgument*/ true)
&& valueType.symbol;
if (isRequireAlias) {
if (isRequireAlias || node.kind === SyntaxKind.ImportType) {
typeType = getTypeReferenceType(node, valueType.symbol);
}
}
@ -12898,8 +12899,7 @@ namespace ts {
/*resolvedReturnType*/ undefined,
/*resolvedTypePredicate*/ undefined,
signature.minArgumentCount,
signature.hasRestParameter,
signature.hasLiteralTypes);
signature.flags & SignatureFlags.PropagatingFlags);
result.target = signature;
result.mapper = mapper;
return result;
@ -13852,7 +13852,7 @@ namespace ts {
*/
function isAnySignature(s: Signature) {
return !s.typeParameters && (!s.thisParameter || isTypeAny(getTypeOfParameter(s.thisParameter))) && s.parameters.length === 1 &&
s.hasRestParameter && (getTypeOfParameter(s.parameters[0]) === anyArrayType || isTypeAny(getTypeOfParameter(s.parameters[0]))) &&
signatureHasRestParameter(s) && (getTypeOfParameter(s.parameters[0]) === anyArrayType || isTypeAny(getTypeOfParameter(s.parameters[0]))) &&
isTypeAny(getReturnTypeOfSignature(s));
}
@ -16677,48 +16677,22 @@ namespace ts {
return strictNullChecks ? getUnionType([type, optionalType]) : type;
}
function isNotOptionalTypeMarker(type: Type) {
return type !== optionalType;
}
function removeOptionalTypeMarker(type: Type): Type {
return strictNullChecks ? filterType(type, t => t !== optionalType) : type;
return strictNullChecks ? filterType(type, isNotOptionalTypeMarker) : type;
}
function propagateOptionalTypeMarker(type: Type, wasOptional: boolean) {
return wasOptional ? addOptionalTypeMarker(type) : type;
}
function createPooledOptionalTypeResult(isOptional: boolean, type: Type) {
pooledOptionalTypeResult.isOptional = isOptional;
pooledOptionalTypeResult.type = type;
return pooledOptionalTypeResult;
}
function checkOptionalExpression(
parent: PropertyAccessExpression | QualifiedName | ElementAccessExpression | CallExpression,
expression: Expression | QualifiedName,
nullDiagnostic?: DiagnosticMessage,
undefinedDiagnostic?: DiagnosticMessage,
nullOrUndefinedDiagnostic?: DiagnosticMessage,
) {
let isOptional = false;
let type = checkExpression(expression);
if (isOptionalChain(parent)) {
if (parent.questionDotToken) {
// If we have a questionDotToken then we are an OptionalExpression and should remove `null` and
// `undefined` from the type and add the optionalType to the result, if needed.
isOptional = isNullableType(type);
return createPooledOptionalTypeResult(isOptional, isOptional ? getNonNullableType(type) : type);
}
// If we do not have a questionDotToken, then we are an OptionalChain and we remove the optionalType and
// indicate whether we need to add optionalType back into the result.
const nonOptionalType = removeOptionalTypeMarker(type);
if (nonOptionalType !== type) {
isOptional = true;
type = nonOptionalType;
}
}
type = checkNonNullType(type, expression, nullDiagnostic, undefinedDiagnostic, nullOrUndefinedDiagnostic);
return createPooledOptionalTypeResult(isOptional, type);
function getOptionalExpressionType(exprType: Type, expression: Expression) {
return isExpressionOfOptionalChainRoot(expression) ? getNonNullableType(exprType) :
isOptionalChain(expression) ? removeOptionalTypeMarker(exprType) :
exprType;
}
/**
@ -17375,10 +17349,7 @@ namespace ts {
// inferring a type parameter constraint. Instead, make a lower priority inference from
// the full source to whatever remains in the target. For example, when inferring from
// string to 'string | T', make a lower priority inference of string for T.
const savePriority = priority;
priority |= InferencePriority.NakedTypeVariable;
inferFromTypes(source, target);
priority = savePriority;
inferWithPriority(source, target, InferencePriority.NakedTypeVariable);
return;
}
source = getUnionType(sources);
@ -17480,10 +17451,7 @@ namespace ts {
else if ((isLiteralType(source) || source.flags & TypeFlags.String) && target.flags & TypeFlags.Index) {
const empty = createEmptyObjectTypeFromStringLiteral(source);
contravariant = !contravariant;
const savePriority = priority;
priority |= InferencePriority.LiteralKeyof;
inferFromTypes(empty, (target as IndexType).type);
priority = savePriority;
inferWithPriority(empty, (target as IndexType).type, InferencePriority.LiteralKeyof);
contravariant = !contravariant;
}
else if (source.flags & TypeFlags.IndexedAccess && target.flags & TypeFlags.IndexedAccess) {
@ -17535,6 +17503,13 @@ namespace ts {
}
}
function inferWithPriority(source: Type, target: Type, newPriority: InferencePriority) {
const savePriority = priority;
priority |= newPriority;
inferFromTypes(source, target);
priority = savePriority;
}
function invokeOnce(source: Type, target: Type, action: (source: Type, target: Type) => void) {
const key = source.id + "," + target.id;
const status = visited && visited.get(key);
@ -17602,6 +17577,18 @@ namespace ts {
return undefined;
}
function getSingleTypeVariableFromIntersectionTypes(types: Type[]) {
let typeVariable: Type | undefined;
for (const type of types) {
const t = type.flags & TypeFlags.Intersection && find((<IntersectionType>type).types, t => !!getInferenceInfoForType(t));
if (!t || typeVariable && t !== typeVariable) {
return undefined;
}
typeVariable = t;
}
return typeVariable;
}
function inferToMultipleTypes(source: Type, targets: Type[], targetFlags: TypeFlags) {
let typeVariableCount = 0;
if (targetFlags & TypeFlags.Union) {
@ -17629,6 +17616,16 @@ namespace ts {
}
}
}
if (typeVariableCount === 0) {
// If every target is an intersection of types containing a single naked type variable,
// make a lower priority inference to that type variable. This handles inferring from
// 'A | B' to 'T & (X | Y)' where we want to infer 'A | B' for T.
const intersectionTypeVariable = getSingleTypeVariableFromIntersectionTypes(targets);
if (intersectionTypeVariable) {
inferWithPriority(source, intersectionTypeVariable, InferencePriority.NakedTypeVariable);
}
return;
}
// If the target has a single naked type variable and no inference circularities were
// encountered above (meaning we explored the types fully), create a union of the source
// types from which no inferences have been made so far and infer from that union to the
@ -17659,14 +17656,11 @@ namespace ts {
// we want to infer string for T, not Promise<string> | string. For intersection types
// we only infer to single naked type variables.
if (targetFlags & TypeFlags.Intersection ? typeVariableCount === 1 : typeVariableCount > 0) {
const savePriority = priority;
priority |= InferencePriority.NakedTypeVariable;
for (const t of targets) {
if (getInferenceInfoForType(t)) {
inferFromTypes(source, t);
inferWithPriority(source, t, InferencePriority.NakedTypeVariable);
}
}
priority = savePriority;
}
}
@ -17687,14 +17681,13 @@ namespace ts {
if (inference && !inference.isFixed) {
const inferredType = inferTypeForHomomorphicMappedType(source, target, <IndexType>constraintType);
if (inferredType) {
const savePriority = priority;
// We assign a lower priority to inferences made from types containing non-inferrable
// types because we may only have a partial result (i.e. we may have failed to make
// reverse inferences for some properties).
priority |= getObjectFlags(source) & ObjectFlags.NonInferrableType ?
InferencePriority.PartialHomomorphicMappedType : InferencePriority.HomomorphicMappedType;
inferFromTypes(inferredType, inference.typeParameter);
priority = savePriority;
inferWithPriority(inferredType, inference.typeParameter,
getObjectFlags(source) & ObjectFlags.NonInferrableType ?
InferencePriority.PartialHomomorphicMappedType :
InferencePriority.HomomorphicMappedType);
}
}
return true;
@ -17702,10 +17695,7 @@ namespace ts {
if (constraintType.flags & TypeFlags.TypeParameter) {
// We're inferring from some source type S to a mapped type { [P in K]: X }, where K is a type
// parameter. First infer from 'keyof S' to K.
const savePriority = priority;
priority |= InferencePriority.MappedTypeConstraint;
inferFromTypes(getIndexType(source), constraintType);
priority = savePriority;
inferWithPriority(getIndexType(source), constraintType, InferencePriority.MappedTypeConstraint);
// If K is constrained to a type C, also infer to C. Thus, for a mapped type { [P in K]: X },
// where K extends keyof T, we make the same inferences as for a homomorphic mapped type
// { [P in keyof T]: X }. This enables us to make meaningful inferences when the target is a
@ -18762,9 +18752,21 @@ namespace ts {
// expressions are potential type predicate function calls. In order to avoid triggering
// circularities in control flow analysis, we use getTypeOfDottedName when resolving the call
// target expression of an assertion.
const funcType = node.parent.kind === SyntaxKind.ExpressionStatement ? getTypeOfDottedName(node.expression, /*diagnostic*/ undefined) :
node.expression.kind !== SyntaxKind.SuperKeyword ? checkOptionalExpression(node, node.expression).type :
undefined;
let funcType: Type | undefined;
if (node.parent.kind === SyntaxKind.ExpressionStatement) {
funcType = getTypeOfDottedName(node.expression, /*diagnostic*/ undefined);
}
else if (node.expression.kind !== SyntaxKind.SuperKeyword) {
if (isOptionalChain(node)) {
funcType = checkNonNullType(
getOptionalExpressionType(checkExpression(node.expression), node.expression),
node.expression
);
}
else {
funcType = checkNonNullExpression(node.expression);
}
}
const signatures = getSignaturesOfType(funcType && getApparentType(funcType) || unknownType, SignatureKind.Call);
const candidate = signatures.length === 1 && !signatures[0].typeParameters ? signatures[0] :
some(signatures, hasTypePredicateOrNeverReturnType) ? getResolvedSignature(node) :
@ -18779,6 +18781,14 @@ namespace ts {
signature.declaration && (getReturnTypeFromAnnotation(signature.declaration) || unknownType).flags & TypeFlags.Never);
}
function getTypePredicateArgument(predicate: TypePredicate, callExpression: CallExpression) {
if (predicate.kind === TypePredicateKind.Identifier || predicate.kind === TypePredicateKind.AssertsIdentifier) {
return callExpression.arguments[predicate.parameterIndex];
}
const invokedExpression = skipParentheses(callExpression.expression);
return isAccessExpression(invokedExpression) ? skipParentheses(invokedExpression.expression) : undefined;
}
function reportFlowControlError(node: Node) {
const block = <Block | ModuleBlock | SourceFile>findAncestor(node, isFunctionOrModuleBlock);
const sourceFile = getSourceFileOfNode(node);
@ -19167,20 +19177,30 @@ namespace ts {
if (isMatchingReference(reference, expr)) {
type = narrowTypeBySwitchOnDiscriminant(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
}
else if (isMatchingReferenceDiscriminant(expr, type)) {
type = narrowTypeByDiscriminant(
type,
expr as AccessExpression,
t => narrowTypeBySwitchOnDiscriminant(t, flow.switchStatement, flow.clauseStart, flow.clauseEnd));
}
else if (expr.kind === SyntaxKind.TypeOfExpression && isMatchingReference(reference, (expr as TypeOfExpression).expression)) {
type = narrowBySwitchOnTypeOf(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
}
else if (containsMatchingReferenceDiscriminant(reference, expr)) {
type = declaredType;
}
else if (flow.clauseStart === flow.clauseEnd && isExhaustiveSwitchStatement(flow.switchStatement)) {
return unreachableNeverType;
else {
if (strictNullChecks) {
if (optionalChainContainsReference(expr, reference)) {
type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd,
t => !(t.flags & (TypeFlags.Undefined | TypeFlags.Never)));
}
else if (expr.kind === SyntaxKind.TypeOfExpression && optionalChainContainsReference((expr as TypeOfExpression).expression, reference)) {
type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd,
t => !(t.flags & TypeFlags.Never || t.flags & TypeFlags.StringLiteral && (<StringLiteralType>t).value === "undefined"));
}
}
if (isMatchingReferenceDiscriminant(expr, type)) {
type = narrowTypeByDiscriminant(type, expr as AccessExpression,
t => narrowTypeBySwitchOnDiscriminant(t, flow.switchStatement, flow.clauseStart, flow.clauseEnd));
}
else if (containsMatchingReferenceDiscriminant(reference, expr)) {
type = declaredType;
}
else if (flow.clauseStart === flow.clauseEnd && isExhaustiveSwitchStatement(flow.switchStatement)) {
return unreachableNeverType;
}
}
return createFlowType(type, isIncomplete(flowType));
}
@ -19325,6 +19345,9 @@ namespace ts {
if (isMatchingReference(reference, expr)) {
return getTypeWithFacts(type, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy);
}
if (strictNullChecks && assumeTrue && optionalChainContainsReference(expr, reference)) {
type = getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
}
if (isMatchingReferenceDiscriminant(expr, declaredType)) {
return narrowTypeByDiscriminant(type, <AccessExpression>expr, t => getTypeWithFacts(t, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy));
}
@ -19376,12 +19399,12 @@ namespace ts {
if (isMatchingReference(reference, right)) {
return narrowTypeByEquality(type, operator, left, assumeTrue);
}
if (assumeTrue && strictNullChecks) {
if (strictNullChecks) {
if (optionalChainContainsReference(left, reference)) {
type = narrowTypeByOptionalChainContainment(type, operator, right);
type = narrowTypeByOptionalChainContainment(type, operator, right, assumeTrue);
}
else if (optionalChainContainsReference(right, reference)) {
type = narrowTypeByOptionalChainContainment(type, operator, left);
type = narrowTypeByOptionalChainContainment(type, operator, left, assumeTrue);
}
}
if (isMatchingReferenceDiscriminant(left, declaredType)) {
@ -19408,16 +19431,14 @@ namespace ts {
return type;
}
function narrowTypeByOptionalChainContainment(type: Type, operator: SyntaxKind, value: Expression): Type {
// We are in the true branch of obj?.foo === value or obj?.foo !== value. We remove undefined and null from
function narrowTypeByOptionalChainContainment(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type {
// We are in a branch of obj?.foo === value or obj?.foo !== value. We remove undefined and null from
// the type of obj if (a) the operator is === and the type of value doesn't include undefined or (b) the
// operator is !== and the type of value is undefined.
const valueType = getTypeOfExpression(value);
return operator === SyntaxKind.EqualsEqualsToken && !(getTypeFacts(valueType) & TypeFacts.EQUndefinedOrNull) ||
operator === SyntaxKind.EqualsEqualsEqualsToken && !(getTypeFacts(valueType) & TypeFacts.EQUndefined) ||
operator === SyntaxKind.ExclamationEqualsToken && valueType.flags & TypeFlags.Nullable ||
operator === SyntaxKind.ExclamationEqualsEqualsToken && valueType.flags & TypeFlags.Undefined ?
getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
const effectiveTrue = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken ? assumeTrue : !assumeTrue;
const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken;
const valueNonNullish = !(getTypeFacts(getTypeOfExpression(value)) & (doubleEquals ? TypeFacts.EQUndefinedOrNull : TypeFacts.EQUndefined));
return effectiveTrue === valueNonNullish ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
}
function narrowTypeByEquality(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type {
@ -19468,10 +19489,12 @@ namespace ts {
function narrowTypeByTypeof(type: Type, typeOfExpr: TypeOfExpression, operator: SyntaxKind, literal: LiteralExpression, assumeTrue: boolean): Type {
// We have '==', '!=', '===', or !==' operator with 'typeof xxx' and string literal operands
if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
assumeTrue = !assumeTrue;
}
const target = getReferenceCandidate(typeOfExpr.expression);
if (!isMatchingReference(reference, target)) {
if (assumeTrue && (operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken) &&
strictNullChecks && optionalChainContainsReference(target, reference)) {
if (strictNullChecks && optionalChainContainsReference(target, reference) && assumeTrue === (literal.text !== "undefined")) {
return getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
}
// For a reference of the form 'x.y', a 'typeof x === ...' type guard resets the
@ -19481,9 +19504,6 @@ namespace ts {
}
return type;
}
if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
assumeTrue = !assumeTrue;
}
if (type.flags & TypeFlags.Any && literal.text === "function") {
return type;
}
@ -19518,6 +19538,11 @@ namespace ts {
}
}
function narrowTypeBySwitchOptionalChainContainment(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number, clauseCheck: (type: Type) => boolean) {
const everyClauseChecks = clauseStart !== clauseEnd && every(getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd), clauseCheck);
return everyClauseChecks ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
}
function narrowTypeBySwitchOnDiscriminant(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) {
// We only narrow if all case expressions specify
// values with unit types, except for the case where
@ -19738,32 +19763,21 @@ namespace ts {
function narrowTypeByTypePredicate(type: Type, predicate: TypePredicate, callExpression: CallExpression, assumeTrue: boolean): Type {
// Don't narrow from 'any' if the predicate type is exactly 'Object' or 'Function'
if (isTypeAny(type) && (predicate.type === globalObjectType || predicate.type === globalFunctionType)) {
return type;
}
if (predicate.kind === TypePredicateKind.Identifier || predicate.kind === TypePredicateKind.AssertsIdentifier) {
const predicateArgument = callExpression.arguments[predicate.parameterIndex];
if (predicateArgument && predicate.type) {
if (predicate.type && !(isTypeAny(type) && (predicate.type === globalObjectType || predicate.type === globalFunctionType))) {
const predicateArgument = getTypePredicateArgument(predicate, callExpression);
if (predicateArgument) {
if (isMatchingReference(reference, predicateArgument)) {
return getNarrowedType(type, predicate.type, assumeTrue, isTypeSubtypeOf);
}
if (strictNullChecks && assumeTrue && optionalChainContainsReference(predicateArgument, reference) &&
!(getTypeFacts(predicate.type) & TypeFacts.EQUndefined)) {
return getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull);
}
if (containsMatchingReference(reference, predicateArgument)) {
return declaredType;
}
}
}
else {
const invokedExpression = skipParentheses(callExpression.expression);
if (isAccessExpression(invokedExpression) && predicate.type) {
const possibleReference = skipParentheses(invokedExpression.expression);
if (isMatchingReference(reference, possibleReference)) {
return getNarrowedType(type, predicate.type, assumeTrue, isTypeSubtypeOf);
}
if (containsMatchingReference(reference, possibleReference)) {
return declaredType;
}
}
}
return type;
}
@ -19771,7 +19785,7 @@ namespace ts {
// will be a subtype or the same type as the argument.
function narrowType(type: Type, expr: Expression, assumeTrue: boolean): Type {
// for `a?.b`, we emulate a synthetic `a !== null && a !== undefined` condition for `a`
if (isOptionalChainRoot(expr.parent) ||
if (isExpressionOfOptionalChainRoot(expr) ||
isBinaryExpression(expr.parent) && expr.parent.operatorToken.kind === SyntaxKind.QuestionQuestionToken && expr.parent.left === expr) {
return narrowTypeByOptionality(type, expr, assumeTrue);
}
@ -22673,19 +22687,8 @@ namespace ts {
return !!forEachProperty(symbol, prop => !(prop.flags & SymbolFlags.Method));
}
function checkNonNullExpression(
node: Expression | QualifiedName,
nullDiagnostic?: DiagnosticMessage,
undefinedDiagnostic?: DiagnosticMessage,
nullOrUndefinedDiagnostic?: DiagnosticMessage,
) {
return checkNonNullType(
checkExpression(node),
node,
nullDiagnostic,
undefinedDiagnostic,
nullOrUndefinedDiagnostic
);
function checkNonNullExpression(node: Expression | QualifiedName) {
return checkNonNullType(checkExpression(node), node);
}
function isNullableType(type: Type) {
@ -22696,12 +22699,26 @@ namespace ts {
return isNullableType(type) ? getNonNullableType(type) : type;
}
function checkNonNullType(
function reportObjectPossiblyNullOrUndefinedError(node: Node, flags: TypeFlags) {
error(node, flags & TypeFlags.Undefined ? flags & TypeFlags.Null ?
Diagnostics.Object_is_possibly_null_or_undefined :
Diagnostics.Object_is_possibly_undefined :
Diagnostics.Object_is_possibly_null
);
}
function reportCannotInvokePossiblyNullOrUndefinedError(node: Node, flags: TypeFlags) {
error(node, flags & TypeFlags.Undefined ? flags & TypeFlags.Null ?
Diagnostics.Cannot_invoke_an_object_which_is_possibly_null_or_undefined :
Diagnostics.Cannot_invoke_an_object_which_is_possibly_undefined :
Diagnostics.Cannot_invoke_an_object_which_is_possibly_null
);
}
function checkNonNullTypeWithReporter(
type: Type,
node: Node,
nullDiagnostic?: DiagnosticMessage,
undefinedDiagnostic?: DiagnosticMessage,
nullOrUndefinedDiagnostic?: DiagnosticMessage
reportError: (node: Node, kind: TypeFlags) => void
): Type {
if (strictNullChecks && type.flags & TypeFlags.Unknown) {
error(node, Diagnostics.Object_is_of_type_unknown);
@ -22709,17 +22726,17 @@ namespace ts {
}
const kind = (strictNullChecks ? getFalsyFlags(type) : type.flags) & TypeFlags.Nullable;
if (kind) {
error(node, kind & TypeFlags.Undefined ? kind & TypeFlags.Null ?
(nullOrUndefinedDiagnostic || Diagnostics.Object_is_possibly_null_or_undefined) :
(undefinedDiagnostic || Diagnostics.Object_is_possibly_undefined) :
(nullDiagnostic || Diagnostics.Object_is_possibly_null)
);
reportError(node, kind);
const t = getNonNullableType(type);
return t.flags & (TypeFlags.Nullable | TypeFlags.Never) ? errorType : t;
}
return type;
}
function checkNonNullType(type: Type, node: Node) {
return checkNonNullTypeWithReporter(type, node, reportObjectPossiblyNullOrUndefinedError);
}
function checkNonNullNonVoidType(type: Type, node: Node): Type {
const nonNullType = checkNonNullType(type, node);
if (nonNullType !== errorType && nonNullType.flags & TypeFlags.Void) {
@ -22729,11 +22746,18 @@ namespace ts {
}
function checkPropertyAccessExpression(node: PropertyAccessExpression) {
return checkPropertyAccessExpressionOrQualifiedName(node, node.expression, node.name);
return node.flags & NodeFlags.OptionalChain ? checkPropertyAccessChain(node as PropertyAccessChain) :
checkPropertyAccessExpressionOrQualifiedName(node, node.expression, checkNonNullExpression(node.expression), node.name);
}
function checkPropertyAccessChain(node: PropertyAccessChain) {
const leftType = checkExpression(node.expression);
const nonOptionalType = getOptionalExpressionType(leftType, node.expression);
return propagateOptionalTypeMarker(checkPropertyAccessExpressionOrQualifiedName(node, node.expression, checkNonNullType(nonOptionalType, node.expression), node.name), nonOptionalType !== leftType);
}
function checkQualifiedName(node: QualifiedName) {
return checkPropertyAccessExpressionOrQualifiedName(node, node.left, node.right);
return checkPropertyAccessExpressionOrQualifiedName(node, node.left, checkNonNullExpression(node.left), node.right);
}
function isMethodAccessForCall(node: Node) {
@ -22743,8 +22767,7 @@ namespace ts {
return isCallOrNewExpression(node.parent) && node.parent.expression === node;
}
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) {
const { isOptional, type: leftType } = checkOptionalExpression(node, left);
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, leftType: Type, right: Identifier) {
const parentSymbol = getNodeLinks(left).resolvedSymbol;
const assignmentKind = getAssignmentTargetKind(node);
const apparentType = getApparentType(assignmentKind !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(leftType) : leftType);
@ -22798,7 +22821,7 @@ namespace ts {
}
propType = getConstraintForLocation(getTypeOfSymbol(prop), node);
}
return propagateOptionalTypeMarker(getFlowTypeOfAccessExpression(node, prop, propType, right), isOptional);
return getFlowTypeOfAccessExpression(node, prop, propType, right);
}
function getFlowTypeOfAccessExpression(node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, prop: Symbol | undefined, propType: Type, errorNode: Node) {
@ -23155,7 +23178,17 @@ namespace ts {
}
function checkIndexedAccess(node: ElementAccessExpression): Type {
const { isOptional, type: exprType } = checkOptionalExpression(node, node.expression);
return node.flags & NodeFlags.OptionalChain ? checkElementAccessChain(node as ElementAccessChain) :
checkElementAccessExpression(node, checkNonNullExpression(node.expression));
}
function checkElementAccessChain(node: ElementAccessChain) {
const exprType = checkExpression(node.expression);
const nonOptionalType = getOptionalExpressionType(exprType, node.expression);
return propagateOptionalTypeMarker(checkElementAccessExpression(node, checkNonNullType(nonOptionalType, node.expression)), nonOptionalType !== exprType);
}
function checkElementAccessExpression(node: ElementAccessExpression, exprType: Type): Type {
const objectType = getAssignmentTargetKind(node) !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(exprType) : exprType;
const indexExpression = node.argumentExpression;
const indexType = checkExpression(indexExpression);
@ -23174,7 +23207,7 @@ namespace ts {
AccessFlags.Writing | (isGenericObjectType(objectType) && !isThisTypeParameter(objectType) ? AccessFlags.NoIndexSignatures : 0) :
AccessFlags.None;
const indexedAccessType = getIndexedAccessTypeOrUndefined(objectType, effectiveIndexType, node, accessFlags) || errorType;
return propagateOptionalTypeMarker(checkIndexedAccessIndexType(getFlowTypeOfAccessExpression(node, indexedAccessType.symbol, indexedAccessType, indexExpression), node), isOptional);
return checkIndexedAccessIndexType(getFlowTypeOfAccessExpression(node, indexedAccessType.symbol, indexedAccessType, indexExpression), node);
}
function checkThatExpressionIsProperSymbolReference(expression: Expression, expressionType: Type, reportError: boolean): boolean {
@ -23287,7 +23320,7 @@ namespace ts {
// specialized signatures always need to be placed before non-specialized signatures regardless
// of the cutoff position; see GH#1133
if (signature.hasLiteralTypes) {
if (signatureHasLiteralTypes(signature)) {
specializedIndex++;
spliceIndex = specializedIndex;
// The cutoff index always needs to be greater than or equal to the specialized signature index
@ -23299,7 +23332,7 @@ namespace ts {
spliceIndex = index;
}
result.splice(spliceIndex, 0, isOptionalCall ? createOptionalCallSignature(signature) : signature);
result.splice(spliceIndex, 0, isOptionalCall ? getOptionalCallSignature(signature) : signature);
}
}
@ -24257,17 +24290,21 @@ namespace ts {
const { min: minArgumentCount, max: maxNonRestParam } = minAndMax(candidates, getNumNonRestParameters);
const parameters: Symbol[] = [];
for (let i = 0; i < maxNonRestParam; i++) {
const symbols = mapDefined(candidates, ({ parameters, hasRestParameter }) => hasRestParameter ?
i < parameters.length - 1 ? parameters[i] : last(parameters) :
i < parameters.length ? parameters[i] : undefined);
const symbols = mapDefined(candidates, s => signatureHasRestParameter(s) ?
i < s.parameters.length - 1 ? s.parameters[i] : last(s.parameters) :
i < s.parameters.length ? s.parameters[i] : undefined);
Debug.assert(symbols.length !== 0);
parameters.push(createCombinedSymbolFromTypes(symbols, mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i))));
}
const restParameterSymbols = mapDefined(candidates, c => c.hasRestParameter ? last(c.parameters) : undefined);
const hasRestParameter = restParameterSymbols.length !== 0;
if (hasRestParameter) {
const restParameterSymbols = mapDefined(candidates, c => signatureHasRestParameter(c) ? last(c.parameters) : undefined);
let flags = SignatureFlags.None;
if (restParameterSymbols.length !== 0) {
const type = createArrayType(getUnionType(mapDefined(candidates, tryGetRestTypeOfSignature), UnionReduction.Subtype));
parameters.push(createCombinedSymbolForOverloadFailure(restParameterSymbols, type));
flags |= SignatureFlags.HasRestParameter;
}
if (candidates.some(signatureHasLiteralTypes)) {
flags |= SignatureFlags.HasLiteralTypes;
}
return createSignature(
candidates[0].declaration,
@ -24277,13 +24314,12 @@ namespace ts {
/*resolvedReturnType*/ getIntersectionType(candidates.map(getReturnTypeOfSignature)),
/*typePredicate*/ undefined,
minArgumentCount,
hasRestParameter,
/*hasLiteralTypes*/ candidates.some(c => c.hasLiteralTypes));
flags);
}
function getNumNonRestParameters(signature: Signature): number {
const numParams = signature.parameters.length;
return signature.hasRestParameter ? numParams - 1 : numParams;
return signatureHasRestParameter(signature) ? numParams - 1 : numParams;
}
function createCombinedSymbolFromTypes(sources: readonly Symbol[], types: Type[]): Symbol {
@ -24374,12 +24410,20 @@ namespace ts {
return resolveUntypedCall(node);
}
const { isOptional, type: funcType } = checkOptionalExpression(
node,
let isOptional: boolean;
let funcType = checkExpression(node.expression);
if (isCallChain(node)) {
const nonOptionalType = getOptionalExpressionType(funcType, node.expression);
isOptional = nonOptionalType !== funcType;
funcType = nonOptionalType;
}
else {
isOptional = false;
}
funcType = checkNonNullTypeWithReporter(
funcType,
node.expression,
Diagnostics.Cannot_invoke_an_object_which_is_possibly_null,
Diagnostics.Cannot_invoke_an_object_which_is_possibly_undefined,
Diagnostics.Cannot_invoke_an_object_which_is_possibly_null_or_undefined
reportCannotInvokePossiblyNullOrUndefinedError
);
if (funcType === silentNeverType) {
@ -24833,8 +24877,7 @@ namespace ts {
typeSymbol ? getDeclaredTypeOfSymbol(typeSymbol) : errorType,
/*returnTypePredicate*/ undefined,
1,
/*hasRestparameter*/ false,
/*hasLiteralTypes*/ false
SignatureFlags.None
);
}
@ -24873,7 +24916,7 @@ namespace ts {
function isPotentiallyUncalledDecorator(decorator: Decorator, signatures: readonly Signature[]) {
return signatures.length && every(signatures, signature =>
signature.minArgumentCount === 0 &&
!signature.hasRestParameter &&
!signatureHasRestParameter(signature) &&
signature.parameters.length < getDecoratorArgumentCount(decorator, signature));
}
@ -24947,7 +24990,7 @@ namespace ts {
}
function mergeJSSymbols(target: Symbol, source: Symbol | undefined) {
if (source && (hasEntries(source.exports) || hasEntries(source.members))) {
if (source) {
const links = getSymbolLinks(source);
if (!links.inferredClassSymbol || !links.inferredClassSymbol.has("" + getSymbolId(target))) {
const inferred = isTransientSymbol(target) ? target : cloneSymbol(target) as TransientSymbol;
@ -25289,7 +25332,7 @@ namespace ts {
}
function getParameterNameAtPosition(signature: Signature, pos: number) {
const paramCount = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
if (pos < paramCount) {
return signature.parameters[pos].escapedName;
}
@ -25308,11 +25351,11 @@ namespace ts {
}
function tryGetTypeAtPosition(signature: Signature, pos: number): Type | undefined {
const paramCount = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
if (pos < paramCount) {
return getTypeOfParameter(signature.parameters[pos]);
}
if (signature.hasRestParameter) {
if (signatureHasRestParameter(signature)) {
// We want to return the value undefined for an out of bounds parameter position,
// so we need to check bounds here before calling getIndexedAccessType (which
// otherwise would return the type 'undefined').
@ -25349,7 +25392,7 @@ namespace ts {
function getParameterCount(signature: Signature) {
const length = signature.parameters.length;
if (signature.hasRestParameter) {
if (signatureHasRestParameter(signature)) {
const restType = getTypeOfSymbol(signature.parameters[length - 1]);
if (isTupleType(restType)) {
return length + getTypeArguments(restType).length - 1;
@ -25359,7 +25402,7 @@ namespace ts {
}
function getMinArgumentCount(signature: Signature) {
if (signature.hasRestParameter) {
if (signatureHasRestParameter(signature)) {
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
if (isTupleType(restType)) {
const minLength = restType.target.minLength;
@ -25372,7 +25415,7 @@ namespace ts {
}
function hasEffectiveRestParameter(signature: Signature) {
if (signature.hasRestParameter) {
if (signatureHasRestParameter(signature)) {
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
return !isTupleType(restType) || restType.target.hasRestElement;
}
@ -25380,7 +25423,7 @@ namespace ts {
}
function getEffectiveRestType(signature: Signature) {
if (signature.hasRestParameter) {
if (signatureHasRestParameter(signature)) {
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
return isTupleType(restType) ? getRestArrayTypeOfTupleType(restType) : restType;
}
@ -25401,7 +25444,7 @@ namespace ts {
}
function inferFromAnnotatedParameters(signature: Signature, context: Signature, inferenceContext: InferenceContext) {
const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
const len = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
for (let i = 0; i < len; i++) {
const declaration = <ParameterDeclaration>signature.parameters[i].valueDeclaration;
if (declaration.type) {
@ -25435,7 +25478,7 @@ namespace ts {
assignTypeToParameterAndFixTypeParameters(signature.thisParameter!, getTypeOfSymbol(context.thisParameter));
}
}
const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
const len = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
for (let i = 0; i < len; i++) {
const parameter = signature.parameters[i];
if (!getEffectiveTypeAnnotationNode(<ParameterDeclaration>parameter.valueDeclaration)) {
@ -25443,7 +25486,7 @@ namespace ts {
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType);
}
}
if (signature.hasRestParameter) {
if (signatureHasRestParameter(signature)) {
// parameter might be a transient symbol generated by use of `arguments` in the function body.
const parameter = last(signature.parameters);
if (isTransientSymbol(parameter) || !getEffectiveTypeAnnotationNode(<ParameterDeclaration>parameter.valueDeclaration)) {
@ -25881,7 +25924,7 @@ namespace ts {
return links.contextFreeType;
}
const returnType = getReturnTypeFromBody(node, checkMode);
const returnOnlySignature = createSignature(undefined, undefined, undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const returnOnlySignature = createSignature(undefined, undefined, undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
const returnOnlyType = createAnonymousType(node.symbol, emptySymbols, [returnOnlySignature], emptyArray, undefined, undefined);
returnOnlyType.objectFlags |= ObjectFlags.NonInferrableType;
return links.contextFreeType = returnOnlyType;
@ -27346,7 +27389,18 @@ namespace ts {
// 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 (isCallExpression(expr) && expr.expression.kind !== SyntaxKind.SuperKeyword && !isRequireCall(expr, /*checkArgumentIsStringLiteralLike*/ true) && !isSymbolOrSymbolForCall(expr)) {
const { isOptional, type: funcType } = checkOptionalExpression(expr, expr.expression);
let isOptional: boolean;
let funcType: Type;
if (isCallChain(expr)) {
funcType = checkExpression(expr.expression);
const nonOptionalType = getOptionalExpressionType(funcType, expr.expression);
isOptional = funcType !== nonOptionalType;
funcType = checkNonNullType(nonOptionalType, expr.expression);
}
else {
isOptional = false;
funcType = checkNonNullExpression(expr.expression);
}
const signature = getSingleCallSignature(funcType);
if (signature && !signature.typeParameters) {
return propagateOptionalTypeMarker(getReturnTypeOfSignature(signature), isOptional);
@ -27621,7 +27675,7 @@ namespace ts {
}
else {
if (typePredicate.parameterIndex >= 0) {
if (signature.hasRestParameter && typePredicate.parameterIndex === signature.parameters.length - 1) {
if (signatureHasRestParameter(signature) && typePredicate.parameterIndex === signature.parameters.length - 1) {
error(parameterName, Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter);
}
else {
@ -36053,4 +36107,16 @@ namespace ts {
case IterationTypeKind.Next: return "nextType";
}
}
export function signatureHasRestParameter(s: Signature) {
return !!(s.flags & SignatureFlags.HasRestParameter);
}
export function signatureHasLiteralTypes(s: Signature) {
return !!(s.flags & SignatureFlags.HasLiteralTypes);
}
export function signatureIsOptionalCall(s: Signature) {
return !!(s.flags & SignatureFlags.IsOptionalCall);
}
}

View file

@ -1,7 +1,7 @@
namespace ts {
// WARNING: The script `configureNightly.ts` uses a regexp to parse out these values.
// If changing the text in this section, be sure to test `configureNightly` too.
export const versionMajorMinor = "3.7";
export const versionMajorMinor = "3.8";
/** The version of the TypeScript compiler release */
export const version = `${versionMajorMinor}.0-dev`;
}

View file

@ -96,35 +96,51 @@ namespace ts {
if (existingDirectories.has(directoryPath)) {
return true;
}
if (system.directoryExists(directoryPath)) {
if ((compilerHost.directoryExists || system.directoryExists)(directoryPath)) {
existingDirectories.set(directoryPath, true);
return true;
}
return false;
}
function ensureDirectoriesExist(directoryPath: string) {
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
const parentDirectory = getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
if (compilerHost.createDirectory) {
compilerHost.createDirectory(directoryPath);
}
else {
system.createDirectory(directoryPath);
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
try {
performance.mark("beforeIOWrite");
// NOTE: If patchWriteFileEnsuringDirectory has been called,
// the system.writeFile will do its own directory creation and
// the ensureDirectoriesExist call will always be redundant.
writeFileEnsuringDirectories(
fileName,
data,
writeByteOrderMark,
(path, data, writeByteOrderMark) => writeFileWorker(path, data, writeByteOrderMark),
path => (compilerHost.createDirectory || system.createDirectory)(path),
path => directoryExists(path));
performance.mark("afterIOWrite");
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
}
catch (e) {
if (onError) {
onError(e.message);
}
}
}
let outputFingerprints: Map<OutputFingerprint>;
function writeFileWorker(fileName: string, data: string, writeByteOrderMark: boolean) {
if (!isWatchSet(options) || !system.createHash || !system.getModifiedTime) {
system.writeFile(fileName, data, writeByteOrderMark);
return;
}
function writeFileIfUpdated(fileName: string, data: string, writeByteOrderMark: boolean): void {
if (!outputFingerprints) {
outputFingerprints = createMap<OutputFingerprint>();
}
const hash = system.createHash!(data); // TODO: GH#18217
const mtimeBefore = system.getModifiedTime!(fileName); // TODO: GH#18217
const hash = system.createHash(data);
const mtimeBefore = system.getModifiedTime(fileName);
if (mtimeBefore) {
const fingerprint = outputFingerprints.get(fileName);
@ -139,7 +155,7 @@ namespace ts {
system.writeFile(fileName, data, writeByteOrderMark);
const mtimeAfter = system.getModifiedTime!(fileName) || missingFileModifiedTime; // TODO: GH#18217
const mtimeAfter = system.getModifiedTime(fileName) || missingFileModifiedTime;
outputFingerprints.set(fileName, {
hash,
@ -148,28 +164,6 @@ namespace ts {
});
}
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
try {
performance.mark("beforeIOWrite");
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
if (isWatchSet(options) && system.createHash && system.getModifiedTime) {
writeFileIfUpdated(fileName, data, writeByteOrderMark);
}
else {
system.writeFile(fileName, data, writeByteOrderMark);
}
performance.mark("afterIOWrite");
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
}
catch (e) {
if (onError) {
onError(e.message);
}
}
}
function getDefaultLibLocation(): string {
return getDirectoryPath(normalizePath(system.getExecutingFilePath()));
}

View file

@ -522,17 +522,6 @@ namespace ts {
}
}
function recursiveCreateDirectory(directoryPath: string, sys: System) {
const basePath = getDirectoryPath(directoryPath);
const shouldCreateParent = basePath !== "" && directoryPath !== basePath && !sys.directoryExists(basePath);
if (shouldCreateParent) {
recursiveCreateDirectory(basePath, sys);
}
if (shouldCreateParent || !sys.directoryExists(directoryPath)) {
sys.createDirectory(directoryPath);
}
}
/**
* patch writefile to create folder before writing the file
*/
@ -540,13 +529,14 @@ namespace ts {
export function patchWriteFileEnsuringDirectory(sys: System) {
// patch writefile to create folder before writing the file
const originalWriteFile = sys.writeFile;
sys.writeFile = (path, data, writeBom) => {
const directoryPath = getDirectoryPath(normalizeSlashes(path));
if (directoryPath && !sys.directoryExists(directoryPath)) {
recursiveCreateDirectory(directoryPath, sys);
}
originalWriteFile.call(sys, path, data, writeBom);
};
sys.writeFile = (path, data, writeBom) =>
writeFileEnsuringDirectories(
path,
data,
!!writeBom,
(path, data, writeByteOrderMark) => originalWriteFile.call(sys, path, data, writeByteOrderMark),
path => sys.createDirectory(path),
path => sys.directoryExists(path));
}
/*@internal*/

View file

@ -3451,8 +3451,7 @@ namespace ts {
resolvedReturnType: Type,
typePredicate: TypePredicate | undefined,
minArgumentCount: number,
hasRestParameter: boolean,
hasLiteralTypes: boolean,
flags: SignatureFlags
): Signature;
/* @internal */ createSymbol(flags: SymbolFlags, name: __String): TransientSymbol;
/* @internal */ createIndexInfo(type: Type, isReadonly: boolean, declaration?: SignatureDeclaration): IndexInfo;
@ -4671,7 +4670,22 @@ namespace ts {
Construct,
}
/* @internal */
export const enum SignatureFlags {
None = 0,
HasRestParameter = 1 << 0, // Indicates last parameter is rest parameter
HasLiteralTypes = 1 << 1, // Indicates signature is specialized
IsOptionalCall = 1 << 2, // Indicates signature comes from a CallChain
// We do not propagate `IsOptionalCall` to instantiated signatures, as that would result in us
// attempting to add `| undefined` on each recursive call to `getReturnTypeOfSignature` when
// instantiating the return type.
PropagatingFlags = HasRestParameter | HasLiteralTypes,
}
export interface Signature {
/* @internal */ flags: SignatureFlags;
/* @internal */ checker?: TypeChecker;
declaration?: SignatureDeclaration | JSDocSignature; // Originating declaration
typeParameters?: readonly TypeParameter[]; // Type parameters (undefined if non-generic)
parameters: readonly Symbol[]; // Parameters
@ -4688,10 +4702,6 @@ namespace ts {
/* @internal */
minArgumentCount: number; // Number of non-optional parameters
/* @internal */
hasRestParameter: boolean; // True if last parameter is rest parameter
/* @internal */
hasLiteralTypes: boolean; // True if specialized
/* @internal */
target?: Signature; // Instantiation target
/* @internal */
mapper?: TypeMapper; // Instantiation mapper
@ -4702,11 +4712,11 @@ namespace ts {
/* @internal */
canonicalSignatureCache?: Signature; // Canonical version of signature (deferred)
/* @internal */
optionalCallSignatureCache?: Signature; // Optional chained call version of signature (deferred)
/* @internal */
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
/* @internal */
instantiations?: Map<Signature>; // Generic signature instantiation cache
/* @internal */
isOptionalCall?: boolean;
}
export const enum IndexKind {
@ -6442,6 +6452,7 @@ namespace ts {
readonly disableSuggestions?: boolean;
readonly quotePreference?: "auto" | "double" | "single";
readonly includeCompletionsForModuleExports?: boolean;
readonly includeAutomaticOptionalChainCompletions?: boolean;
readonly includeCompletionsWithInsertText?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
/** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */

View file

@ -2061,26 +2061,30 @@ namespace ts {
isBindableStaticNameExpression(expr.arguments[0], /*excludeThisKeyword*/ true);
}
export function isBindableStaticElementAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticElementAccessExpression {
return isLiteralLikeElementAccess(node)
&& ((!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword) ||
isEntityNameExpression(node.expression) ||
isBindableStaticElementAccessExpression(node.expression, /*excludeThisKeyword*/ true));
}
/** x.y OR x[0] */
export function isLiteralLikeAccess(node: Node): node is LiteralLikeElementAccessExpression | PropertyAccessExpression {
return isPropertyAccessExpression(node) || isLiteralLikeElementAccess(node);
}
/** x[0] OR x['a'] OR x[Symbol.y] */
export function isLiteralLikeElementAccess(node: Node): node is LiteralLikeElementAccessExpression {
return isElementAccessExpression(node) && (
isStringOrNumericLiteralLike(node.argumentExpression) ||
isWellKnownSymbolSyntactically(node.argumentExpression));
}
/** Any series of property and element accesses. */
export function isBindableStaticAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticAccessExpression {
return isPropertyAccessExpression(node) && (!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword || isBindableStaticNameExpression(node.expression, /*excludeThisKeyword*/ true))
|| isBindableStaticElementAccessExpression(node, excludeThisKeyword);
|| isBindableStaticElementAccessExpression(node, excludeThisKeyword);
}
/** Any series of property and element accesses, ending in a literal element access */
export function isBindableStaticElementAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticElementAccessExpression {
return isLiteralLikeElementAccess(node)
&& ((!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword) ||
isEntityNameExpression(node.expression) ||
isBindableStaticAccessExpression(node.expression, /*excludeThisKeyword*/ true));
}
export function isBindableStaticNameExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticNameExpression {
@ -2111,7 +2115,7 @@ namespace ts {
if (expr.operatorToken.kind !== SyntaxKind.EqualsToken || !isAccessExpression(expr.left)) {
return AssignmentDeclarationKind.None;
}
if (isBindableStaticNameExpression(expr.left.expression) && getElementOrPropertyAccessName(expr.left) === "prototype" && isObjectLiteralExpression(getInitializerOfBinaryExpression(expr))) {
if (isBindableStaticNameExpression(expr.left.expression, /*excludeThisKeyword*/ true) && getElementOrPropertyAccessName(expr.left) === "prototype" && isObjectLiteralExpression(getInitializerOfBinaryExpression(expr))) {
// F.prototype = { ... }
return AssignmentDeclarationKind.Prototype;
}
@ -2179,8 +2183,10 @@ namespace ts {
// exports.name = expr OR module.exports.name = expr OR exports["name"] = expr ...
return AssignmentDeclarationKind.ExportsProperty;
}
// F.G...x = expr
return AssignmentDeclarationKind.Property;
if (isBindableStaticNameExpression(lhs, /*excludeThisKeyword*/ true) || (isElementAccessExpression(lhs) && isDynamicName(lhs) && lhs.expression.kind !== SyntaxKind.ThisKeyword)) {
// F.G...x = expr
return AssignmentDeclarationKind.Property;
}
}
return AssignmentDeclarationKind.None;
@ -3700,6 +3706,36 @@ namespace ts {
}, sourceFiles);
}
function ensureDirectoriesExist(
directoryPath: string,
createDirectory: (path: string) => void,
directoryExists: (path: string) => boolean): void {
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
const parentDirectory = getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory, createDirectory, directoryExists);
createDirectory(directoryPath);
}
}
export function writeFileEnsuringDirectories(
path: string,
data: string,
writeByteOrderMark: boolean,
writeFile: (path: string, data: string, writeByteOrderMark: boolean) => void,
createDirectory: (path: string) => void,
directoryExists: (path: string) => boolean): void {
// PERF: Checking for directory existence is expensive. Instead, assume the directory exists
// and fall back to creating it if the file write fails.
try {
writeFile(path, data, writeByteOrderMark);
}
catch {
ensureDirectoriesExist(getDirectoryPath(normalizePath(path)), createDirectory, directoryExists);
writeFile(path, data, writeByteOrderMark);
}
}
export function getLineOfLocalPosition(currentSourceFile: SourceFile, pos: number) {
return getLineAndCharacterOfPosition(currentSourceFile, pos).line;
}
@ -5911,6 +5947,18 @@ namespace ts {
|| kind === SyntaxKind.CallExpression);
}
/**
* Determines whether a node is the expression preceding an optional chain (i.e. `a` in `a?.b`).
*/
/* @internal */
export function isExpressionOfOptionalChainRoot(node: Node): node is Expression & { parent: OptionalChainRoot } {
return isOptionalChainRoot(node.parent) && node.parent.expression === node;
}
export function isNullishCoalesce(node: Node) {
return node.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node).operatorToken.kind === SyntaxKind.QuestionQuestionToken;
}
export function isNewExpression(node: Node): node is NewExpression {
return node.kind === SyntaxKind.NewExpression;
}
@ -7310,7 +7358,7 @@ namespace ts {
getSourceFileConstructor(): new (kind: SyntaxKind.SourceFile, pos?: number, end?: number) => SourceFile;
getSymbolConstructor(): new (flags: SymbolFlags, name: __String) => Symbol;
getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type;
getSignatureConstructor(): new (checker: TypeChecker) => Signature;
getSignatureConstructor(): new (checker: TypeChecker, flags: SignatureFlags) => Signature;
getSourceMapSourceConstructor(): new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource;
}
@ -7331,7 +7379,12 @@ namespace ts {
}
}
function Signature() {}
function Signature(this: Signature, checker: TypeChecker, flags: SignatureFlags) {
this.flags = flags;
if (Debug.isDebugging) {
this.checker = checker;
}
}
function Node(this: Node, kind: SyntaxKind, pos: number, end: number) {
this.pos = pos;

View file

@ -303,20 +303,20 @@ namespace ts {
readDirectory: maybeBind(host, host.readDirectory),
};
function ensureDirectoriesExist(directoryPath: string) {
if (directoryPath.length > getRootLength(directoryPath) && !host.directoryExists!(directoryPath)) {
const parentDirectory = getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
if (host.createDirectory) host.createDirectory(directoryPath);
}
}
function writeFile(fileName: string, text: string, writeByteOrderMark: boolean, onError: (message: string) => void) {
try {
performance.mark("beforeIOWrite");
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
host.writeFile!(fileName, text, writeByteOrderMark);
// NOTE: If patchWriteFileEnsuringDirectory has been called,
// the host.writeFile will do its own directory creation and
// the ensureDirectoriesExist call will always be redundant.
writeFileEnsuringDirectories(
fileName,
text,
writeByteOrderMark,
(path, data, writeByteOrderMark) => host.writeFile!(path, data, writeByteOrderMark),
path => host.createDirectory!(path),
path => host.directoryExists!(path));
performance.mark("afterIOWrite");
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");

View file

@ -1359,9 +1359,12 @@ namespace ts.server {
return;
}
// Search our peer node_modules, then any globally-specified probe paths
// ../../.. to walk from X/node_modules/typescript/lib/tsserver.js to X/node_modules/
const searchPaths = [combinePaths(this.projectService.getExecutingFilePath(), "../../.."), ...this.projectService.pluginProbeLocations];
// Search any globally-specified probe paths, then our peer node_modules
const searchPaths = [
...this.projectService.pluginProbeLocations,
// ../../.. to walk from X/node_modules/typescript/lib/tsserver.js to X/node_modules/
combinePaths(this.projectService.getExecutingFilePath(), "../../.."),
];
if (this.projectService.globalPlugins) {
// Enable global plugins with synthetic configuration entries

View file

@ -3007,6 +3007,12 @@ namespace ts.server.protocol {
* For those entries, The `insertText` and `replacementSpan` properties will be set to change from `.x` property access to `["x"]`.
*/
readonly includeCompletionsWithInsertText?: boolean;
/**
* Unless this option is `false`, or `includeCompletionsWithInsertText` is not enabled,
* member completion lists triggered with `.` will include entries on potentially-null and potentially-undefined
* values, with insertion text to replace preceding `.` tokens with `?.`.
*/
readonly includeAutomaticOptionalChainCompletions?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
readonly allowTextChangesInNewFiles?: boolean;
readonly lazyConfiguredProjectsFromExternalProject?: boolean;

View file

@ -233,14 +233,14 @@ namespace ts.codefix {
let someSigHasRestParameter = false;
for (const sig of signatures) {
minArgumentCount = Math.min(sig.minArgumentCount, minArgumentCount);
if (sig.hasRestParameter) {
if (signatureHasRestParameter(sig)) {
someSigHasRestParameter = true;
}
if (sig.parameters.length >= maxArgsSignature.parameters.length && (!sig.hasRestParameter || maxArgsSignature.hasRestParameter)) {
if (sig.parameters.length >= maxArgsSignature.parameters.length && (!signatureHasRestParameter(sig) || signatureHasRestParameter(maxArgsSignature))) {
maxArgsSignature = sig;
}
}
const maxNonRestArgs = maxArgsSignature.parameters.length - (maxArgsSignature.hasRestParameter ? 1 : 0);
const maxNonRestArgs = maxArgsSignature.parameters.length - (signatureHasRestParameter(maxArgsSignature) ? 1 : 0);
const maxArgsParameterSymbolNames = maxArgsSignature.parameters.map(symbol => symbol.name);
const parameters = createDummyParameters(maxNonRestArgs, maxArgsParameterSymbolNames, /* types */ undefined, minArgumentCount, /*inJs*/ false);

View file

@ -1112,7 +1112,7 @@ namespace ts.codefix {
}
const returnType = combineFromUsage(combineUsages(calls.map(call => call.return_)));
// TODO: GH#18217
return checker.createSignature(/*declaration*/ undefined!, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, length, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
return checker.createSignature(/*declaration*/ undefined!, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, length, SignatureFlags.None);
}
function addCandidateType(usage: Usage, type: Type | undefined) {

View file

@ -338,6 +338,7 @@ namespace ts.Completions {
): CompletionEntry | undefined {
let insertText: string | undefined;
let replacementSpan: TextSpan | undefined;
const insertQuestionDot = origin && originIsNullableMember(origin);
const useBraces = origin && originIsSymbolMember(origin) || needsConvertPropertyAccess;
if (origin && originIsThisType(origin)) {
@ -780,7 +781,7 @@ namespace ts.Completions {
sourceFile: SourceFile,
isUncheckedFile: boolean,
position: number,
preferences: Pick<UserPreferences, "includeCompletionsForModuleExports" | "includeCompletionsWithInsertText">,
preferences: Pick<UserPreferences, "includeCompletionsForModuleExports" | "includeCompletionsWithInsertText" | "includeAutomaticOptionalChainCompletions">,
detailsEntryId: CompletionEntryIdentifier | undefined,
host: LanguageServiceHost,
): CompletionData | Request | undefined {
@ -1116,8 +1117,17 @@ namespace ts.Completions {
let type = typeChecker.getTypeOfSymbolAtLocation(symbol, node).getNonOptionalType();
let insertQuestionDot = false;
if (type.isNullableType()) {
insertQuestionDot = isRightOfDot && !isRightOfQuestionDot;
type = type.getNonNullableType();
const canCorrectToQuestionDot =
isRightOfDot &&
!isRightOfQuestionDot &&
preferences.includeAutomaticOptionalChainCompletions !== false;
if (canCorrectToQuestionDot || isRightOfQuestionDot) {
type = type.getNonNullableType();
if (canCorrectToQuestionDot) {
insertQuestionDot = true;
}
}
}
addTypeProperties(type, !!(node.flags & NodeFlags.AwaitContext), insertQuestionDot);
}
@ -1137,8 +1147,17 @@ namespace ts.Completions {
let type = typeChecker.getTypeAtLocation(node).getNonOptionalType();
let insertQuestionDot = false;
if (type.isNullableType()) {
insertQuestionDot = isRightOfDot && !isRightOfQuestionDot;
type = type.getNonNullableType();
const canCorrectToQuestionDot =
isRightOfDot &&
!isRightOfQuestionDot &&
preferences.includeAutomaticOptionalChainCompletions !== false;
if (canCorrectToQuestionDot || isRightOfQuestionDot) {
type = type.getNonNullableType();
if (canCorrectToQuestionDot) {
insertQuestionDot = true;
}
}
}
addTypeProperties(type, !!(node.flags & NodeFlags.AwaitContext), insertQuestionDot);
}

View file

@ -584,7 +584,7 @@ namespace ts.FindAllReferences.Core {
}
function getReferencedSymbolsForModuleIfDeclaredBySourceFile(symbol: Symbol, program: Program, sourceFiles: readonly SourceFile[], cancellationToken: CancellationToken, options: Options, sourceFilesSet: ReadonlyMap<true>) {
const moduleSourceFile = symbol.flags & SymbolFlags.Module ? find(symbol.declarations, isSourceFile) : undefined;
const moduleSourceFile = (symbol.flags & SymbolFlags.Module) && symbol.declarations && find(symbol.declarations, isSourceFile);
if (!moduleSourceFile) return undefined;
const exportEquals = symbol.exports!.get(InternalSymbolName.ExportEquals);
// If !!exportEquals, we're about to add references to `import("mod")` anyway, so don't double-count them.

View file

@ -648,7 +648,8 @@ namespace ts.NavigationBar {
const declName = getNameOfDeclaration(<Declaration>node);
if (declName && isPropertyName(declName)) {
return unescapeLeadingUnderscores(getPropertyNameForPropertyNameNode(declName)!); // TODO: GH#18217
const propertyName = getPropertyNameForPropertyNameNode(declName);
return propertyName && unescapeLeadingUnderscores(propertyName);
}
switch (node.kind) {
case SyntaxKind.FunctionExpression:

View file

@ -464,6 +464,7 @@ namespace ts {
}
class SignatureObject implements Signature {
flags: SignatureFlags;
checker: TypeChecker;
declaration!: SignatureDeclaration;
typeParameters?: TypeParameter[];
@ -473,8 +474,6 @@ namespace ts {
resolvedTypePredicate: TypePredicate | undefined;
minTypeArgumentCount!: number;
minArgumentCount!: number;
hasRestParameter!: boolean;
hasLiteralTypes!: boolean;
// Undefined is used to indicate the value has not been computed. If, after computing, the
// symbol has no doc comment, then the empty array will be returned.
@ -484,9 +483,11 @@ namespace ts {
// symbol has no doc comment, then the empty array will be returned.
jsDocTags?: JSDocTagInfo[];
constructor(checker: TypeChecker) {
constructor(checker: TypeChecker, flags: SignatureFlags) {
this.checker = checker;
this.flags = flags;
}
getDeclaration(): SignatureDeclaration {
return this.declaration;
}

View file

@ -204,7 +204,7 @@ namespace ts.Completions.StringCompletions {
const candidates: Signature[] = [];
checker.getResolvedSignature(argumentInfo.invocation, candidates, argumentInfo.argumentCount);
const types = flatMap(candidates, candidate => {
if (!candidate.hasRestParameter && argumentInfo.argumentCount > candidate.parameters.length) return;
if (!signatureHasRestParameter(candidate) && argumentInfo.argumentCount > candidate.parameters.length) return;
const type = checker.getParameterType(candidate, argumentInfo.argumentIndex);
isNewIdentifier = isNewIdentifier || !!(type.flags & TypeFlags.String);
return getStringLiteralTypes(type, uniques);

View file

@ -1,5 +1,5 @@
{
"extends": "../tsconfig-base",
"extends": "./tsconfig.json",
"compilerOptions": {
"outFile": "../../built/local/tsc.release.js",
"stripInternal": true,
@ -8,11 +8,8 @@
"declarationMap": false,
"sourceMap": false,
"composite": false,
"incremental": true
"incremental": true
},
"files": [
"tsc.ts"
],
"references": [
{ "path": "../compiler/tsconfig.release.json", "prepend": true }
]

View file

@ -0,0 +1,142 @@
//// [tests/cases/compiler/anonClassDeclarationEmitIsAnon.ts] ////
//// [wrapClass.ts]
export function wrapClass(param: any) {
return class Wrapped {
foo() {
return param;
}
}
}
export type Constructor<T = {}> = new (...args: any[]) => T;
export function Timestamped<TBase extends Constructor>(Base: TBase) {
return class extends Base {
timestamp = Date.now();
};
}
//// [index.ts]
import { wrapClass, Timestamped } from "./wrapClass";
export default wrapClass(0);
// Simple class
export class User {
name = '';
}
// User that is Timestamped
export class TimestampedUser extends Timestamped(User) {
constructor() {
super();
}
}
//// [wrapClass.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
function wrapClass(param) {
return /** @class */ (function () {
function Wrapped() {
}
Wrapped.prototype.foo = function () {
return param;
};
return Wrapped;
}());
}
exports.wrapClass = wrapClass;
function Timestamped(Base) {
return /** @class */ (function (_super) {
__extends(class_1, _super);
function class_1() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.timestamp = Date.now();
return _this;
}
return class_1;
}(Base));
}
exports.Timestamped = Timestamped;
//// [index.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var wrapClass_1 = require("./wrapClass");
exports["default"] = wrapClass_1.wrapClass(0);
// Simple class
var User = /** @class */ (function () {
function User() {
this.name = '';
}
return User;
}());
exports.User = User;
// User that is Timestamped
var TimestampedUser = /** @class */ (function (_super) {
__extends(TimestampedUser, _super);
function TimestampedUser() {
return _super.call(this) || this;
}
return TimestampedUser;
}(wrapClass_1.Timestamped(User)));
exports.TimestampedUser = TimestampedUser;
//// [wrapClass.d.ts]
export declare function wrapClass(param: any): {
new (): {
foo(): any;
};
};
export declare type Constructor<T = {}> = new (...args: any[]) => T;
export declare function Timestamped<TBase extends Constructor>(Base: TBase): {
new (...args: any[]): {
timestamp: number;
};
} & TBase;
//// [index.d.ts]
declare const _default: {
new (): {
foo(): any;
};
};
export default _default;
export declare class User {
name: string;
}
declare const TimestampedUser_base: {
new (...args: any[]): {
timestamp: number;
};
} & typeof User;
export declare class TimestampedUser extends TimestampedUser_base {
constructor();
}

View file

@ -0,0 +1,68 @@
=== tests/cases/compiler/wrapClass.ts ===
export function wrapClass(param: any) {
>wrapClass : Symbol(wrapClass, Decl(wrapClass.ts, 0, 0))
>param : Symbol(param, Decl(wrapClass.ts, 0, 26))
return class Wrapped {
>Wrapped : Symbol(Wrapped, Decl(wrapClass.ts, 1, 10))
foo() {
>foo : Symbol(Wrapped.foo, Decl(wrapClass.ts, 1, 26))
return param;
>param : Symbol(param, Decl(wrapClass.ts, 0, 26))
}
}
}
export type Constructor<T = {}> = new (...args: any[]) => T;
>Constructor : Symbol(Constructor, Decl(wrapClass.ts, 6, 1))
>T : Symbol(T, Decl(wrapClass.ts, 8, 24))
>args : Symbol(args, Decl(wrapClass.ts, 8, 39))
>T : Symbol(T, Decl(wrapClass.ts, 8, 24))
export function Timestamped<TBase extends Constructor>(Base: TBase) {
>Timestamped : Symbol(Timestamped, Decl(wrapClass.ts, 8, 60))
>TBase : Symbol(TBase, Decl(wrapClass.ts, 10, 28))
>Constructor : Symbol(Constructor, Decl(wrapClass.ts, 6, 1))
>Base : Symbol(Base, Decl(wrapClass.ts, 10, 55))
>TBase : Symbol(TBase, Decl(wrapClass.ts, 10, 28))
return class extends Base {
>Base : Symbol(Base, Decl(wrapClass.ts, 10, 55))
timestamp = Date.now();
>timestamp : Symbol((Anonymous class).timestamp, Decl(wrapClass.ts, 11, 31))
>Date.now : Symbol(DateConstructor.now, Decl(lib.es5.d.ts, --, --))
>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --))
>now : Symbol(DateConstructor.now, Decl(lib.es5.d.ts, --, --))
};
}
=== tests/cases/compiler/index.ts ===
import { wrapClass, Timestamped } from "./wrapClass";
>wrapClass : Symbol(wrapClass, Decl(index.ts, 0, 8))
>Timestamped : Symbol(Timestamped, Decl(index.ts, 0, 19))
export default wrapClass(0);
>wrapClass : Symbol(wrapClass, Decl(index.ts, 0, 8))
// Simple class
export class User {
>User : Symbol(User, Decl(index.ts, 2, 28))
name = '';
>name : Symbol(User.name, Decl(index.ts, 5, 19))
}
// User that is Timestamped
export class TimestampedUser extends Timestamped(User) {
>TimestampedUser : Symbol(TimestampedUser, Decl(index.ts, 7, 1))
>Timestamped : Symbol(Timestamped, Decl(index.ts, 0, 19))
>User : Symbol(User, Decl(index.ts, 2, 28))
constructor() {
super();
}
}

View file

@ -0,0 +1,72 @@
=== tests/cases/compiler/wrapClass.ts ===
export function wrapClass(param: any) {
>wrapClass : (param: any) => typeof Wrapped
>param : any
return class Wrapped {
>class Wrapped { foo() { return param; } } : typeof Wrapped
>Wrapped : typeof Wrapped
foo() {
>foo : () => any
return param;
>param : any
}
}
}
export type Constructor<T = {}> = new (...args: any[]) => T;
>Constructor : Constructor<T>
>args : any[]
export function Timestamped<TBase extends Constructor>(Base: TBase) {
>Timestamped : <TBase extends Constructor<{}>>(Base: TBase) => { new (...args: any[]): (Anonymous class); prototype: Timestamped<any>.(Anonymous class); } & TBase
>Base : TBase
return class extends Base {
>class extends Base { timestamp = Date.now(); } : { new (...args: any[]): (Anonymous class); prototype: Timestamped<any>.(Anonymous class); } & TBase
>Base : {}
timestamp = Date.now();
>timestamp : number
>Date.now() : number
>Date.now : () => number
>Date : DateConstructor
>now : () => number
};
}
=== tests/cases/compiler/index.ts ===
import { wrapClass, Timestamped } from "./wrapClass";
>wrapClass : (param: any) => typeof Wrapped
>Timestamped : <TBase extends import("tests/cases/compiler/wrapClass").Constructor<{}>>(Base: TBase) => { new (...args: any[]): (Anonymous class); prototype: Timestamped<any>.(Anonymous class); } & TBase
export default wrapClass(0);
>wrapClass(0) : typeof Wrapped
>wrapClass : (param: any) => typeof Wrapped
>0 : 0
// Simple class
export class User {
>User : User
name = '';
>name : string
>'' : ""
}
// User that is Timestamped
export class TimestampedUser extends Timestamped(User) {
>TimestampedUser : TimestampedUser
>Timestamped(User) : Timestamped<typeof User>.(Anonymous class) & User
>Timestamped : <TBase extends import("tests/cases/compiler/wrapClass").Constructor<{}>>(Base: TBase) => { new (...args: any[]): (Anonymous class); prototype: Timestamped<any>.(Anonymous class); } & TBase
>User : typeof User
constructor() {
super();
>super() : void
>super : { new (...args: any[]): Timestamped<typeof User>.(Anonymous class); prototype: Timestamped<any>.(Anonymous class); } & typeof User
}
}

View file

@ -14,7 +14,7 @@ and limitations under the License.
***************************************************************************** */
declare namespace ts {
const versionMajorMinor = "3.7";
const versionMajorMinor = "3.8";
/** The version of the TypeScript compiler release */
const version: string;
}
@ -3171,6 +3171,7 @@ declare namespace ts {
readonly disableSuggestions?: boolean;
readonly quotePreference?: "auto" | "double" | "single";
readonly includeCompletionsForModuleExports?: boolean;
readonly includeAutomaticOptionalChainCompletions?: boolean;
readonly includeCompletionsWithInsertText?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
/** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */
@ -3524,6 +3525,7 @@ declare namespace ts {
function isCallExpression(node: Node): node is CallExpression;
function isCallChain(node: Node): node is CallChain;
function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain;
function isNullishCoalesce(node: Node): boolean;
function isNewExpression(node: Node): node is NewExpression;
function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression;
function isTypeAssertion(node: Node): node is TypeAssertion;
@ -8295,6 +8297,12 @@ declare namespace ts.server.protocol {
* For those entries, The `insertText` and `replacementSpan` properties will be set to change from `.x` property access to `["x"]`.
*/
readonly includeCompletionsWithInsertText?: boolean;
/**
* Unless this option is `false`, or `includeCompletionsWithInsertText` is not enabled,
* member completion lists triggered with `.` will include entries on potentially-null and potentially-undefined
* values, with insertion text to replace preceding `.` tokens with `?.`.
*/
readonly includeAutomaticOptionalChainCompletions?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
readonly allowTextChangesInNewFiles?: boolean;
readonly lazyConfiguredProjectsFromExternalProject?: boolean;

View file

@ -14,7 +14,7 @@ and limitations under the License.
***************************************************************************** */
declare namespace ts {
const versionMajorMinor = "3.7";
const versionMajorMinor = "3.8";
/** The version of the TypeScript compiler release */
const version: string;
}
@ -3171,6 +3171,7 @@ declare namespace ts {
readonly disableSuggestions?: boolean;
readonly quotePreference?: "auto" | "double" | "single";
readonly includeCompletionsForModuleExports?: boolean;
readonly includeAutomaticOptionalChainCompletions?: boolean;
readonly includeCompletionsWithInsertText?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
/** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */
@ -3524,6 +3525,7 @@ declare namespace ts {
function isCallExpression(node: Node): node is CallExpression;
function isCallChain(node: Node): node is CallChain;
function isOptionalChain(node: Node): node is PropertyAccessChain | ElementAccessChain | CallChain;
function isNullishCoalesce(node: Node): boolean;
function isNewExpression(node: Node): node is NewExpression;
function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression;
function isTypeAssertion(node: Node): node is TypeAssertion;

View file

@ -0,0 +1,14 @@
tests/cases/conformance/jsdoc/callOfPropertylessConstructorFunction.js(7,1): error TS2348: Value of type 'typeof Dependency' is not callable. Did you mean to include 'new'?
==== tests/cases/conformance/jsdoc/callOfPropertylessConstructorFunction.js (1 errors) ====
/**
* @constructor
*/
function Dependency(j) {
return j
}
Dependency({})
~~~~~~~~~~~~~~
!!! error TS2348: Value of type 'typeof Dependency' is not callable. Did you mean to include 'new'?

View file

@ -0,0 +1,14 @@
=== tests/cases/conformance/jsdoc/callOfPropertylessConstructorFunction.js ===
/**
* @constructor
*/
function Dependency(j) {
>Dependency : Symbol(Dependency, Decl(callOfPropertylessConstructorFunction.js, 0, 0))
>j : Symbol(j, Decl(callOfPropertylessConstructorFunction.js, 3, 20))
return j
>j : Symbol(j, Decl(callOfPropertylessConstructorFunction.js, 3, 20))
}
Dependency({})
>Dependency : Symbol(Dependency, Decl(callOfPropertylessConstructorFunction.js, 0, 0))

View file

@ -0,0 +1,16 @@
=== tests/cases/conformance/jsdoc/callOfPropertylessConstructorFunction.js ===
/**
* @constructor
*/
function Dependency(j) {
>Dependency : typeof Dependency
>j : any
return j
>j : any
}
Dependency({})
>Dependency({}) : any
>Dependency : typeof Dependency
>{} : {}

View file

@ -0,0 +1,18 @@
tests/cases/conformance/jsdoc/0.js(10,20): error TS2694: Namespace 'exports' has no exported member 'SomeName'.
==== tests/cases/conformance/jsdoc/0.js (1 errors) ====
// @ts-check
var exports = {};
/**
* @typedef {string}
*/
exports.SomeName;
/** @type {exports.SomeName} */
~~~~~~~~
!!! error TS2694: Namespace 'exports' has no exported member 'SomeName'.
const myString = 'str';

View file

@ -0,0 +1,23 @@
//// [0.js]
// @ts-check
var exports = {};
/**
* @typedef {string}
*/
exports.SomeName;
/** @type {exports.SomeName} */
const myString = 'str';
//// [0.js]
// @ts-check
var exports = {};
/**
* @typedef {string}
*/
exports.SomeName;
/** @type {exports.SomeName} */
var myString = 'str';

View file

@ -0,0 +1,16 @@
=== tests/cases/conformance/jsdoc/0.js ===
// @ts-check
var exports = {};
>exports : Symbol(exports, Decl(0.js, 2, 3))
/**
* @typedef {string}
*/
exports.SomeName;
>exports : Symbol(exports, Decl(0.js, 2, 3))
/** @type {exports.SomeName} */
const myString = 'str';
>myString : Symbol(myString, Decl(0.js, 10, 5))

View file

@ -0,0 +1,20 @@
=== tests/cases/conformance/jsdoc/0.js ===
// @ts-check
var exports = {};
>exports : {}
>{} : {}
/**
* @typedef {string}
*/
exports.SomeName;
>exports.SomeName : any
>exports : {}
>SomeName : any
/** @type {exports.SomeName} */
const myString = 'str';
>myString : any
>'str' : "str"

View file

@ -31,9 +31,29 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(244,9): error TS
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(271,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(274,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(277,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(307,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(310,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(319,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(322,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(331,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(340,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(343,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(352,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(391,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(394,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(403,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(406,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(415,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(424,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(427,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(436,9): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(471,13): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(474,13): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(488,13): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(491,13): error TS2532: Object is possibly 'undefined'.
==== tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts (33 errors) ====
==== tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts (53 errors) ====
// assignments in shortcutting chain
declare const o: undefined | {
[key: string]: any;
@ -401,6 +421,76 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(277,9): error TS
}
}
function f15(o: Thing | undefined, value: number) {
if (o?.foo === value) {
o.foo;
}
else {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
if (o?.foo !== value) {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
else {
o.foo;
}
if (o?.foo == value) {
o.foo;
}
else {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
if (o?.foo != value) {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
else {
o.foo;
}
}
function f16(o: Thing | undefined) {
if (o?.foo === undefined) {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
else {
o.foo;
}
if (o?.foo !== undefined) {
o.foo;
}
else {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
if (o?.foo == undefined) {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
else {
o.foo;
}
if (o?.foo != undefined) {
o.foo;
}
else {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
}
function f20(o: Thing | undefined) {
if (typeof o?.foo === "number") {
o.foo;
@ -430,4 +520,171 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(277,9): error TS
o.baz;
}
}
function f22(o: Thing | undefined) {
if (typeof o?.foo === "number") {
o.foo;
}
else {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
if (typeof o?.foo !== "number") {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
else {
o.foo;
}
if (typeof o?.foo == "number") {
o.foo;
}
else {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
if (typeof o?.foo != "number") {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
else {
o.foo;
}
}
function f23(o: Thing | undefined) {
if (typeof o?.foo === "undefined") {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
else {
o.foo;
}
if (typeof o?.foo !== "undefined") {
o.foo;
}
else {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
if (typeof o?.foo == "undefined") {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
else {
o.foo;
}
if (typeof o?.foo != "undefined") {
o.foo;
}
else {
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
}
}
declare function assert(x: unknown): asserts x;
declare function assertNonNull<T>(x: T): asserts x is NonNullable<T>;
function f30(o: Thing | undefined) {
if (!!true) {
assert(o?.foo);
o.foo;
}
if (!!true) {
assert(o?.foo === 42);
o.foo;
}
if (!!true) {
assert(typeof o?.foo === "number");
o.foo;
}
if (!!true) {
assertNonNull(o?.foo);
o.foo;
}
}
function f40(o: Thing | undefined) {
switch (o?.foo) {
case "abc":
o.foo;
break;
case 42:
o.foo;
break;
case undefined:
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
break;
default:
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
break;
}
}
function f41(o: Thing | undefined) {
switch (typeof o?.foo) {
case "string":
o.foo;
break;
case "number":
o.foo;
break;
case "undefined":
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
break;
default:
o.foo; // Error
~
!!! error TS2532: Object is possibly 'undefined'.
break;
}
}
// Repros from #34570
type Shape =
| { type: 'rectangle', width: number, height: number }
| { type: 'circle', radius: number }
function getArea(shape?: Shape) {
switch (shape?.type) {
case 'circle':
return Math.PI * shape.radius ** 2
case 'rectangle':
return shape.width * shape.height
default:
return 0
}
}
type Feature = {
id: string;
geometry?: {
type: string;
coordinates: number[];
};
};
function extractCoordinates(f: Feature): number[] {
if (f.geometry?.type !== 'test') {
return [];
}
return f.geometry.coordinates;
}

View file

@ -300,6 +300,60 @@ function f14(o: Thing | null) {
}
}
function f15(o: Thing | undefined, value: number) {
if (o?.foo === value) {
o.foo;
}
else {
o.foo; // Error
}
if (o?.foo !== value) {
o.foo; // Error
}
else {
o.foo;
}
if (o?.foo == value) {
o.foo;
}
else {
o.foo; // Error
}
if (o?.foo != value) {
o.foo; // Error
}
else {
o.foo;
}
}
function f16(o: Thing | undefined) {
if (o?.foo === undefined) {
o.foo; // Error
}
else {
o.foo;
}
if (o?.foo !== undefined) {
o.foo;
}
else {
o.foo; // Error
}
if (o?.foo == undefined) {
o.foo; // Error
}
else {
o.foo;
}
if (o?.foo != undefined) {
o.foo;
}
else {
o.foo; // Error
}
}
function f20(o: Thing | undefined) {
if (typeof o?.foo === "number") {
o.foo;
@ -329,6 +383,149 @@ function f21(o: Thing | null) {
o.baz;
}
}
function f22(o: Thing | undefined) {
if (typeof o?.foo === "number") {
o.foo;
}
else {
o.foo; // Error
}
if (typeof o?.foo !== "number") {
o.foo; // Error
}
else {
o.foo;
}
if (typeof o?.foo == "number") {
o.foo;
}
else {
o.foo; // Error
}
if (typeof o?.foo != "number") {
o.foo; // Error
}
else {
o.foo;
}
}
function f23(o: Thing | undefined) {
if (typeof o?.foo === "undefined") {
o.foo; // Error
}
else {
o.foo;
}
if (typeof o?.foo !== "undefined") {
o.foo;
}
else {
o.foo; // Error
}
if (typeof o?.foo == "undefined") {
o.foo; // Error
}
else {
o.foo;
}
if (typeof o?.foo != "undefined") {
o.foo;
}
else {
o.foo; // Error
}
}
declare function assert(x: unknown): asserts x;
declare function assertNonNull<T>(x: T): asserts x is NonNullable<T>;
function f30(o: Thing | undefined) {
if (!!true) {
assert(o?.foo);
o.foo;
}
if (!!true) {
assert(o?.foo === 42);
o.foo;
}
if (!!true) {
assert(typeof o?.foo === "number");
o.foo;
}
if (!!true) {
assertNonNull(o?.foo);
o.foo;
}
}
function f40(o: Thing | undefined) {
switch (o?.foo) {
case "abc":
o.foo;
break;
case 42:
o.foo;
break;
case undefined:
o.foo; // Error
break;
default:
o.foo; // Error
break;
}
}
function f41(o: Thing | undefined) {
switch (typeof o?.foo) {
case "string":
o.foo;
break;
case "number":
o.foo;
break;
case "undefined":
o.foo; // Error
break;
default:
o.foo; // Error
break;
}
}
// Repros from #34570
type Shape =
| { type: 'rectangle', width: number, height: number }
| { type: 'circle', radius: number }
function getArea(shape?: Shape) {
switch (shape?.type) {
case 'circle':
return Math.PI * shape.radius ** 2
case 'rectangle':
return shape.width * shape.height
default:
return 0
}
}
type Feature = {
id: string;
geometry?: {
type: string;
coordinates: number[];
};
};
function extractCoordinates(f: Feature): number[] {
if (f.geometry?.type !== 'test') {
return [];
}
return f.geometry.coordinates;
}
//// [controlFlowOptionalChain.js]
@ -594,6 +791,60 @@ function f14(o) {
o.bar;
}
}
function f15(o, value) {
var _a, _b, _c, _d;
if (((_a = o) === null || _a === void 0 ? void 0 : _a.foo) === value) {
o.foo;
}
else {
o.foo; // Error
}
if (((_b = o) === null || _b === void 0 ? void 0 : _b.foo) !== value) {
o.foo; // Error
}
else {
o.foo;
}
if (((_c = o) === null || _c === void 0 ? void 0 : _c.foo) == value) {
o.foo;
}
else {
o.foo; // Error
}
if (((_d = o) === null || _d === void 0 ? void 0 : _d.foo) != value) {
o.foo; // Error
}
else {
o.foo;
}
}
function f16(o) {
var _a, _b, _c, _d;
if (((_a = o) === null || _a === void 0 ? void 0 : _a.foo) === undefined) {
o.foo; // Error
}
else {
o.foo;
}
if (((_b = o) === null || _b === void 0 ? void 0 : _b.foo) !== undefined) {
o.foo;
}
else {
o.foo; // Error
}
if (((_c = o) === null || _c === void 0 ? void 0 : _c.foo) == undefined) {
o.foo; // Error
}
else {
o.foo;
}
if (((_d = o) === null || _d === void 0 ? void 0 : _d.foo) != undefined) {
o.foo;
}
else {
o.foo; // Error
}
}
function f20(o) {
var _a, _b, _c, _d;
if (typeof ((_a = o) === null || _a === void 0 ? void 0 : _a.foo) === "number") {
@ -624,3 +875,128 @@ function f21(o) {
o.baz;
}
}
function f22(o) {
var _a, _b, _c, _d;
if (typeof ((_a = o) === null || _a === void 0 ? void 0 : _a.foo) === "number") {
o.foo;
}
else {
o.foo; // Error
}
if (typeof ((_b = o) === null || _b === void 0 ? void 0 : _b.foo) !== "number") {
o.foo; // Error
}
else {
o.foo;
}
if (typeof ((_c = o) === null || _c === void 0 ? void 0 : _c.foo) == "number") {
o.foo;
}
else {
o.foo; // Error
}
if (typeof ((_d = o) === null || _d === void 0 ? void 0 : _d.foo) != "number") {
o.foo; // Error
}
else {
o.foo;
}
}
function f23(o) {
var _a, _b, _c, _d;
if (typeof ((_a = o) === null || _a === void 0 ? void 0 : _a.foo) === "undefined") {
o.foo; // Error
}
else {
o.foo;
}
if (typeof ((_b = o) === null || _b === void 0 ? void 0 : _b.foo) !== "undefined") {
o.foo;
}
else {
o.foo; // Error
}
if (typeof ((_c = o) === null || _c === void 0 ? void 0 : _c.foo) == "undefined") {
o.foo; // Error
}
else {
o.foo;
}
if (typeof ((_d = o) === null || _d === void 0 ? void 0 : _d.foo) != "undefined") {
o.foo;
}
else {
o.foo; // Error
}
}
function f30(o) {
var _a, _b, _c, _d;
if (!!true) {
assert((_a = o) === null || _a === void 0 ? void 0 : _a.foo);
o.foo;
}
if (!!true) {
assert(((_b = o) === null || _b === void 0 ? void 0 : _b.foo) === 42);
o.foo;
}
if (!!true) {
assert(typeof ((_c = o) === null || _c === void 0 ? void 0 : _c.foo) === "number");
o.foo;
}
if (!!true) {
assertNonNull((_d = o) === null || _d === void 0 ? void 0 : _d.foo);
o.foo;
}
}
function f40(o) {
var _a;
switch ((_a = o) === null || _a === void 0 ? void 0 : _a.foo) {
case "abc":
o.foo;
break;
case 42:
o.foo;
break;
case undefined:
o.foo; // Error
break;
default:
o.foo; // Error
break;
}
}
function f41(o) {
var _a;
switch (typeof ((_a = o) === null || _a === void 0 ? void 0 : _a.foo)) {
case "string":
o.foo;
break;
case "number":
o.foo;
break;
case "undefined":
o.foo; // Error
break;
default:
o.foo; // Error
break;
}
}
function getArea(shape) {
var _a;
switch ((_a = shape) === null || _a === void 0 ? void 0 : _a.type) {
case 'circle':
return Math.PI * Math.pow(shape.radius, 2);
case 'rectangle':
return shape.width * shape.height;
default:
return 0;
}
}
function extractCoordinates(f) {
var _a;
if (((_a = f.geometry) === null || _a === void 0 ? void 0 : _a.type) !== 'test') {
return [];
}
return f.geometry.coordinates;
}

View file

@ -1039,93 +1039,627 @@ function f14(o: Thing | null) {
}
}
function f20(o: Thing | undefined) {
>f20 : Symbol(f20, Decl(controlFlowOptionalChain.ts, 299, 1))
function f15(o: Thing | undefined, value: number) {
>f15 : Symbol(f15, Decl(controlFlowOptionalChain.ts, 299, 1))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>Thing : Symbol(Thing, Decl(controlFlowOptionalChain.ts, 159, 1))
>value : Symbol(value, Decl(controlFlowOptionalChain.ts, 301, 34))
if (typeof o?.foo === "number") {
if (o?.foo === value) {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>value : Symbol(value, Decl(controlFlowOptionalChain.ts, 301, 34))
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (typeof o?.["foo"] === "number") {
else {
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (o?.foo !== value) {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>value : Symbol(value, Decl(controlFlowOptionalChain.ts, 301, 34))
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (o?.foo == value) {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>value : Symbol(value, Decl(controlFlowOptionalChain.ts, 301, 34))
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (o?.foo != value) {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>value : Symbol(value, Decl(controlFlowOptionalChain.ts, 301, 34))
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
}
function f16(o: Thing | undefined) {
>f16 : Symbol(f16, Decl(controlFlowOptionalChain.ts, 326, 1))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 328, 13))
>Thing : Symbol(Thing, Decl(controlFlowOptionalChain.ts, 159, 1))
if (o?.foo === undefined) {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 328, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>undefined : Symbol(undefined)
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 328, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 328, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (o?.foo !== undefined) {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 328, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>undefined : Symbol(undefined)
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 328, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 328, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (o?.foo == undefined) {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 328, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>undefined : Symbol(undefined)
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 328, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 328, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (o?.foo != undefined) {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 328, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>undefined : Symbol(undefined)
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 328, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 328, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
}
function f20(o: Thing | undefined) {
>f20 : Symbol(f20, Decl(controlFlowOptionalChain.ts, 353, 1))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 355, 13))
>Thing : Symbol(Thing, Decl(controlFlowOptionalChain.ts, 159, 1))
if (typeof o?.foo === "number") {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 355, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 355, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (typeof o?.["foo"] === "number") {
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 355, 13))
o["foo"];
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 355, 13))
>"foo" : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (typeof o?.bar() === "number") {
>o?.bar : Symbol(bar, Decl(controlFlowOptionalChain.ts, 161, 36))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 355, 13))
>bar : Symbol(bar, Decl(controlFlowOptionalChain.ts, 161, 36))
o.bar;
>o.bar : Symbol(bar, Decl(controlFlowOptionalChain.ts, 161, 36))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 355, 13))
>bar : Symbol(bar, Decl(controlFlowOptionalChain.ts, 161, 36))
}
if (o?.baz instanceof Error) {
>o?.baz : Symbol(baz, Decl(controlFlowOptionalChain.ts, 161, 51))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 355, 13))
>baz : Symbol(baz, Decl(controlFlowOptionalChain.ts, 161, 51))
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
o.baz;
>o.baz : Symbol(baz, Decl(controlFlowOptionalChain.ts, 161, 51))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 301, 13))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 355, 13))
>baz : Symbol(baz, Decl(controlFlowOptionalChain.ts, 161, 51))
}
}
function f21(o: Thing | null) {
>f21 : Symbol(f21, Decl(controlFlowOptionalChain.ts, 314, 1))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 316, 13))
>f21 : Symbol(f21, Decl(controlFlowOptionalChain.ts, 368, 1))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 370, 13))
>Thing : Symbol(Thing, Decl(controlFlowOptionalChain.ts, 159, 1))
if (typeof o?.foo === "number") {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 316, 13))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 370, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 316, 13))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 370, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (typeof o?.["foo"] === "number") {
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 316, 13))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 370, 13))
o["foo"];
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 316, 13))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 370, 13))
>"foo" : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (typeof o?.bar() === "number") {
>o?.bar : Symbol(bar, Decl(controlFlowOptionalChain.ts, 161, 36))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 316, 13))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 370, 13))
>bar : Symbol(bar, Decl(controlFlowOptionalChain.ts, 161, 36))
o.bar;
>o.bar : Symbol(bar, Decl(controlFlowOptionalChain.ts, 161, 36))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 316, 13))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 370, 13))
>bar : Symbol(bar, Decl(controlFlowOptionalChain.ts, 161, 36))
}
if (o?.baz instanceof Error) {
>o?.baz : Symbol(baz, Decl(controlFlowOptionalChain.ts, 161, 51))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 316, 13))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 370, 13))
>baz : Symbol(baz, Decl(controlFlowOptionalChain.ts, 161, 51))
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
o.baz;
>o.baz : Symbol(baz, Decl(controlFlowOptionalChain.ts, 161, 51))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 316, 13))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 370, 13))
>baz : Symbol(baz, Decl(controlFlowOptionalChain.ts, 161, 51))
}
}
function f22(o: Thing | undefined) {
>f22 : Symbol(f22, Decl(controlFlowOptionalChain.ts, 383, 1))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 385, 13))
>Thing : Symbol(Thing, Decl(controlFlowOptionalChain.ts, 159, 1))
if (typeof o?.foo === "number") {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 385, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 385, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 385, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (typeof o?.foo !== "number") {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 385, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 385, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 385, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (typeof o?.foo == "number") {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 385, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 385, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 385, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (typeof o?.foo != "number") {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 385, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 385, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 385, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
}
function f23(o: Thing | undefined) {
>f23 : Symbol(f23, Decl(controlFlowOptionalChain.ts, 410, 1))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 412, 13))
>Thing : Symbol(Thing, Decl(controlFlowOptionalChain.ts, 159, 1))
if (typeof o?.foo === "undefined") {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 412, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 412, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 412, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (typeof o?.foo !== "undefined") {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 412, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 412, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 412, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (typeof o?.foo == "undefined") {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 412, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 412, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 412, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (typeof o?.foo != "undefined") {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 412, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 412, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
else {
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 412, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
}
declare function assert(x: unknown): asserts x;
>assert : Symbol(assert, Decl(controlFlowOptionalChain.ts, 437, 1))
>x : Symbol(x, Decl(controlFlowOptionalChain.ts, 439, 24))
>x : Symbol(x, Decl(controlFlowOptionalChain.ts, 439, 24))
declare function assertNonNull<T>(x: T): asserts x is NonNullable<T>;
>assertNonNull : Symbol(assertNonNull, Decl(controlFlowOptionalChain.ts, 439, 47))
>T : Symbol(T, Decl(controlFlowOptionalChain.ts, 440, 31))
>x : Symbol(x, Decl(controlFlowOptionalChain.ts, 440, 34))
>T : Symbol(T, Decl(controlFlowOptionalChain.ts, 440, 31))
>x : Symbol(x, Decl(controlFlowOptionalChain.ts, 440, 34))
>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(controlFlowOptionalChain.ts, 440, 31))
function f30(o: Thing | undefined) {
>f30 : Symbol(f30, Decl(controlFlowOptionalChain.ts, 440, 69))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 442, 13))
>Thing : Symbol(Thing, Decl(controlFlowOptionalChain.ts, 159, 1))
if (!!true) {
assert(o?.foo);
>assert : Symbol(assert, Decl(controlFlowOptionalChain.ts, 437, 1))
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 442, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 442, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (!!true) {
assert(o?.foo === 42);
>assert : Symbol(assert, Decl(controlFlowOptionalChain.ts, 437, 1))
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 442, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 442, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (!!true) {
assert(typeof o?.foo === "number");
>assert : Symbol(assert, Decl(controlFlowOptionalChain.ts, 437, 1))
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 442, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 442, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
if (!!true) {
assertNonNull(o?.foo);
>assertNonNull : Symbol(assertNonNull, Decl(controlFlowOptionalChain.ts, 439, 47))
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 442, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 442, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
}
}
function f40(o: Thing | undefined) {
>f40 : Symbol(f40, Decl(controlFlowOptionalChain.ts, 459, 1))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 461, 13))
>Thing : Symbol(Thing, Decl(controlFlowOptionalChain.ts, 159, 1))
switch (o?.foo) {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 461, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
case "abc":
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 461, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
break;
case 42:
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 461, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
break;
case undefined:
>undefined : Symbol(undefined)
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 461, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
break;
default:
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 461, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
break;
}
}
function f41(o: Thing | undefined) {
>f41 : Symbol(f41, Decl(controlFlowOptionalChain.ts, 476, 1))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 478, 13))
>Thing : Symbol(Thing, Decl(controlFlowOptionalChain.ts, 159, 1))
switch (typeof o?.foo) {
>o?.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 478, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
case "string":
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 478, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
break;
case "number":
o.foo;
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 478, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
break;
case "undefined":
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 478, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
break;
default:
o.foo; // Error
>o.foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
>o : Symbol(o, Decl(controlFlowOptionalChain.ts, 478, 13))
>foo : Symbol(foo, Decl(controlFlowOptionalChain.ts, 161, 14))
break;
}
}
// Repros from #34570
type Shape =
>Shape : Symbol(Shape, Decl(controlFlowOptionalChain.ts, 493, 1))
| { type: 'rectangle', width: number, height: number }
>type : Symbol(type, Decl(controlFlowOptionalChain.ts, 498, 7))
>width : Symbol(width, Decl(controlFlowOptionalChain.ts, 498, 26))
>height : Symbol(height, Decl(controlFlowOptionalChain.ts, 498, 41))
| { type: 'circle', radius: number }
>type : Symbol(type, Decl(controlFlowOptionalChain.ts, 499, 7))
>radius : Symbol(radius, Decl(controlFlowOptionalChain.ts, 499, 23))
function getArea(shape?: Shape) {
>getArea : Symbol(getArea, Decl(controlFlowOptionalChain.ts, 499, 40))
>shape : Symbol(shape, Decl(controlFlowOptionalChain.ts, 501, 17))
>Shape : Symbol(Shape, Decl(controlFlowOptionalChain.ts, 493, 1))
switch (shape?.type) {
>shape?.type : Symbol(type, Decl(controlFlowOptionalChain.ts, 498, 7), Decl(controlFlowOptionalChain.ts, 499, 7))
>shape : Symbol(shape, Decl(controlFlowOptionalChain.ts, 501, 17))
>type : Symbol(type, Decl(controlFlowOptionalChain.ts, 498, 7), Decl(controlFlowOptionalChain.ts, 499, 7))
case 'circle':
return Math.PI * shape.radius ** 2
>Math.PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --))
>shape.radius : Symbol(radius, Decl(controlFlowOptionalChain.ts, 499, 23))
>shape : Symbol(shape, Decl(controlFlowOptionalChain.ts, 501, 17))
>radius : Symbol(radius, Decl(controlFlowOptionalChain.ts, 499, 23))
case 'rectangle':
return shape.width * shape.height
>shape.width : Symbol(width, Decl(controlFlowOptionalChain.ts, 498, 26))
>shape : Symbol(shape, Decl(controlFlowOptionalChain.ts, 501, 17))
>width : Symbol(width, Decl(controlFlowOptionalChain.ts, 498, 26))
>shape.height : Symbol(height, Decl(controlFlowOptionalChain.ts, 498, 41))
>shape : Symbol(shape, Decl(controlFlowOptionalChain.ts, 501, 17))
>height : Symbol(height, Decl(controlFlowOptionalChain.ts, 498, 41))
default:
return 0
}
}
type Feature = {
>Feature : Symbol(Feature, Decl(controlFlowOptionalChain.ts, 510, 1))
id: string;
>id : Symbol(id, Decl(controlFlowOptionalChain.ts, 512, 16))
geometry?: {
>geometry : Symbol(geometry, Decl(controlFlowOptionalChain.ts, 513, 13))
type: string;
>type : Symbol(type, Decl(controlFlowOptionalChain.ts, 514, 14))
coordinates: number[];
>coordinates : Symbol(coordinates, Decl(controlFlowOptionalChain.ts, 515, 17))
};
};
function extractCoordinates(f: Feature): number[] {
>extractCoordinates : Symbol(extractCoordinates, Decl(controlFlowOptionalChain.ts, 518, 2))
>f : Symbol(f, Decl(controlFlowOptionalChain.ts, 521, 28))
>Feature : Symbol(Feature, Decl(controlFlowOptionalChain.ts, 510, 1))
if (f.geometry?.type !== 'test') {
>f.geometry?.type : Symbol(type, Decl(controlFlowOptionalChain.ts, 514, 14))
>f.geometry : Symbol(geometry, Decl(controlFlowOptionalChain.ts, 513, 13))
>f : Symbol(f, Decl(controlFlowOptionalChain.ts, 521, 28))
>geometry : Symbol(geometry, Decl(controlFlowOptionalChain.ts, 513, 13))
>type : Symbol(type, Decl(controlFlowOptionalChain.ts, 514, 14))
return [];
}
return f.geometry.coordinates;
>f.geometry.coordinates : Symbol(coordinates, Decl(controlFlowOptionalChain.ts, 515, 17))
>f.geometry : Symbol(geometry, Decl(controlFlowOptionalChain.ts, 513, 13))
>f : Symbol(f, Decl(controlFlowOptionalChain.ts, 521, 28))
>geometry : Symbol(geometry, Decl(controlFlowOptionalChain.ts, 513, 13))
>coordinates : Symbol(coordinates, Decl(controlFlowOptionalChain.ts, 515, 17))
}

View file

@ -1170,6 +1170,163 @@ function f14(o: Thing | null) {
}
}
function f15(o: Thing | undefined, value: number) {
>f15 : (o: Thing | undefined, value: number) => void
>o : Thing | undefined
>value : number
if (o?.foo === value) {
>o?.foo === value : boolean
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>value : number
o.foo;
>o.foo : number
>o : Thing
>foo : number
}
else {
o.foo; // Error
>o.foo : string | number
>o : Thing | undefined
>foo : string | number
}
if (o?.foo !== value) {
>o?.foo !== value : boolean
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>value : number
o.foo; // Error
>o.foo : string | number
>o : Thing | undefined
>foo : string | number
}
else {
o.foo;
>o.foo : number
>o : Thing
>foo : number
}
if (o?.foo == value) {
>o?.foo == value : boolean
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>value : number
o.foo;
>o.foo : string | number
>o : Thing
>foo : string | number
}
else {
o.foo; // Error
>o.foo : string | number
>o : Thing | undefined
>foo : string | number
}
if (o?.foo != value) {
>o?.foo != value : boolean
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>value : number
o.foo; // Error
>o.foo : string | number
>o : Thing | undefined
>foo : string | number
}
else {
o.foo;
>o.foo : number
>o : Thing
>foo : number
}
}
function f16(o: Thing | undefined) {
>f16 : (o: Thing | undefined) => void
>o : Thing | undefined
if (o?.foo === undefined) {
>o?.foo === undefined : boolean
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>undefined : undefined
o.foo; // Error
>o.foo : never
>o : Thing | undefined
>foo : never
}
else {
o.foo;
>o.foo : string | number
>o : Thing
>foo : string | number
}
if (o?.foo !== undefined) {
>o?.foo !== undefined : boolean
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>undefined : undefined
o.foo;
>o.foo : string | number
>o : Thing
>foo : string | number
}
else {
o.foo; // Error
>o.foo : never
>o : Thing | undefined
>foo : never
}
if (o?.foo == undefined) {
>o?.foo == undefined : boolean
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>undefined : undefined
o.foo; // Error
>o.foo : never
>o : Thing | undefined
>foo : never
}
else {
o.foo;
>o.foo : string | number
>o : Thing
>foo : string | number
}
if (o?.foo != undefined) {
>o?.foo != undefined : boolean
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>undefined : undefined
o.foo;
>o.foo : string | number
>o : Thing
>foo : string | number
}
else {
o.foo; // Error
>o.foo : never
>o : Thing | undefined
>foo : never
}
}
function f20(o: Thing | undefined) {
>f20 : (o: Thing | undefined) => void
>o : Thing | undefined
@ -1287,3 +1444,445 @@ function f21(o: Thing | null) {
}
}
function f22(o: Thing | undefined) {
>f22 : (o: Thing | undefined) => void
>o : Thing | undefined
if (typeof o?.foo === "number") {
>typeof o?.foo === "number" : boolean
>typeof o?.foo : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>"number" : "number"
o.foo;
>o.foo : number
>o : Thing
>foo : number
}
else {
o.foo; // Error
>o.foo : string
>o : Thing | undefined
>foo : string
}
if (typeof o?.foo !== "number") {
>typeof o?.foo !== "number" : boolean
>typeof o?.foo : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>"number" : "number"
o.foo; // Error
>o.foo : string
>o : Thing | undefined
>foo : string
}
else {
o.foo;
>o.foo : number
>o : Thing
>foo : number
}
if (typeof o?.foo == "number") {
>typeof o?.foo == "number" : boolean
>typeof o?.foo : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>"number" : "number"
o.foo;
>o.foo : number
>o : Thing
>foo : number
}
else {
o.foo; // Error
>o.foo : string
>o : Thing | undefined
>foo : string
}
if (typeof o?.foo != "number") {
>typeof o?.foo != "number" : boolean
>typeof o?.foo : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>"number" : "number"
o.foo; // Error
>o.foo : string
>o : Thing | undefined
>foo : string
}
else {
o.foo;
>o.foo : number
>o : Thing
>foo : number
}
}
function f23(o: Thing | undefined) {
>f23 : (o: Thing | undefined) => void
>o : Thing | undefined
if (typeof o?.foo === "undefined") {
>typeof o?.foo === "undefined" : boolean
>typeof o?.foo : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>"undefined" : "undefined"
o.foo; // Error
>o.foo : never
>o : Thing | undefined
>foo : never
}
else {
o.foo;
>o.foo : string | number
>o : Thing
>foo : string | number
}
if (typeof o?.foo !== "undefined") {
>typeof o?.foo !== "undefined" : boolean
>typeof o?.foo : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>"undefined" : "undefined"
o.foo;
>o.foo : string | number
>o : Thing
>foo : string | number
}
else {
o.foo; // Error
>o.foo : never
>o : Thing | undefined
>foo : never
}
if (typeof o?.foo == "undefined") {
>typeof o?.foo == "undefined" : boolean
>typeof o?.foo : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>"undefined" : "undefined"
o.foo; // Error
>o.foo : never
>o : Thing | undefined
>foo : never
}
else {
o.foo;
>o.foo : string | number
>o : Thing
>foo : string | number
}
if (typeof o?.foo != "undefined") {
>typeof o?.foo != "undefined" : boolean
>typeof o?.foo : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>"undefined" : "undefined"
o.foo;
>o.foo : string | number
>o : Thing
>foo : string | number
}
else {
o.foo; // Error
>o.foo : never
>o : Thing | undefined
>foo : never
}
}
declare function assert(x: unknown): asserts x;
>assert : (x: unknown) => asserts x
>x : unknown
declare function assertNonNull<T>(x: T): asserts x is NonNullable<T>;
>assertNonNull : <T>(x: T) => asserts x is NonNullable<T>
>x : T
function f30(o: Thing | undefined) {
>f30 : (o: Thing | undefined) => void
>o : Thing | undefined
if (!!true) {
>!!true : true
>!true : false
>true : true
assert(o?.foo);
>assert(o?.foo) : void
>assert : (x: unknown) => asserts x
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
o.foo;
>o.foo : string | number
>o : Thing
>foo : string | number
}
if (!!true) {
>!!true : true
>!true : false
>true : true
assert(o?.foo === 42);
>assert(o?.foo === 42) : void
>assert : (x: unknown) => asserts x
>o?.foo === 42 : boolean
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>42 : 42
o.foo;
>o.foo : 42
>o : Thing
>foo : 42
}
if (!!true) {
>!!true : true
>!true : false
>true : true
assert(typeof o?.foo === "number");
>assert(typeof o?.foo === "number") : void
>assert : (x: unknown) => asserts x
>typeof o?.foo === "number" : boolean
>typeof o?.foo : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
>"number" : "number"
o.foo;
>o.foo : number
>o : Thing
>foo : number
}
if (!!true) {
>!!true : true
>!true : false
>true : true
assertNonNull(o?.foo);
>assertNonNull(o?.foo) : void
>assertNonNull : <T>(x: T) => asserts x is NonNullable<T>
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
o.foo;
>o.foo : string | number
>o : Thing
>foo : string | number
}
}
function f40(o: Thing | undefined) {
>f40 : (o: Thing | undefined) => void
>o : Thing | undefined
switch (o?.foo) {
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
case "abc":
>"abc" : "abc"
o.foo;
>o.foo : "abc"
>o : Thing
>foo : "abc"
break;
case 42:
>42 : 42
o.foo;
>o.foo : 42
>o : Thing
>foo : 42
break;
case undefined:
>undefined : undefined
o.foo; // Error
>o.foo : never
>o : Thing | undefined
>foo : never
break;
default:
o.foo; // Error
>o.foo : string | number
>o : Thing | undefined
>foo : string | number
break;
}
}
function f41(o: Thing | undefined) {
>f41 : (o: Thing | undefined) => void
>o : Thing | undefined
switch (typeof o?.foo) {
>typeof o?.foo : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>o?.foo : string | number | undefined
>o : Thing | undefined
>foo : string | number | undefined
case "string":
>"string" : "string"
o.foo;
>o.foo : string
>o : Thing
>foo : string
break;
case "number":
>"number" : "number"
o.foo;
>o.foo : number
>o : Thing
>foo : number
break;
case "undefined":
>"undefined" : "undefined"
o.foo; // Error
>o.foo : never
>o : Thing | undefined
>foo : never
break;
default:
o.foo; // Error
>o.foo : never
>o : Thing | undefined
>foo : never
break;
}
}
// Repros from #34570
type Shape =
>Shape : Shape
| { type: 'rectangle', width: number, height: number }
>type : "rectangle"
>width : number
>height : number
| { type: 'circle', radius: number }
>type : "circle"
>radius : number
function getArea(shape?: Shape) {
>getArea : (shape?: { type: "rectangle"; width: number; height: number; } | { type: "circle"; radius: number; } | undefined) => number
>shape : { type: "rectangle"; width: number; height: number; } | { type: "circle"; radius: number; } | undefined
switch (shape?.type) {
>shape?.type : "rectangle" | "circle" | undefined
>shape : { type: "rectangle"; width: number; height: number; } | { type: "circle"; radius: number; } | undefined
>type : "rectangle" | "circle" | undefined
case 'circle':
>'circle' : "circle"
return Math.PI * shape.radius ** 2
>Math.PI * shape.radius ** 2 : number
>Math.PI : number
>Math : Math
>PI : number
>shape.radius ** 2 : number
>shape.radius : number
>shape : { type: "circle"; radius: number; }
>radius : number
>2 : 2
case 'rectangle':
>'rectangle' : "rectangle"
return shape.width * shape.height
>shape.width * shape.height : number
>shape.width : number
>shape : { type: "rectangle"; width: number; height: number; }
>width : number
>shape.height : number
>shape : { type: "rectangle"; width: number; height: number; }
>height : number
default:
return 0
>0 : 0
}
}
type Feature = {
>Feature : Feature
id: string;
>id : string
geometry?: {
>geometry : { type: string; coordinates: number[]; } | undefined
type: string;
>type : string
coordinates: number[];
>coordinates : number[]
};
};
function extractCoordinates(f: Feature): number[] {
>extractCoordinates : (f: Feature) => number[]
>f : Feature
if (f.geometry?.type !== 'test') {
>f.geometry?.type !== 'test' : boolean
>f.geometry?.type : string | undefined
>f.geometry : { type: string; coordinates: number[]; } | undefined
>f : Feature
>geometry : { type: string; coordinates: number[]; } | undefined
>type : string | undefined
>'test' : "test"
return [];
>[] : never[]
}
return f.geometry.coordinates;
>f.geometry.coordinates : number[]
>f.geometry : { type: string; coordinates: number[]; }
>f : Feature
>geometry : { type: string; coordinates: number[]; }
>coordinates : number[]
}

View file

@ -1,5 +1,8 @@
tests/cases/conformance/salsa/main.js(2,13): error TS2339: Property 'foo' does not exist on type 'Alias'.
tests/cases/conformance/salsa/main.js(4,9): error TS2339: Property 'foo' does not exist on type 'Alias'.
tests/cases/conformance/salsa/main.js(3,13): error TS2339: Property 'func' does not exist on type 'Alias'.
tests/cases/conformance/salsa/main.js(3,38): error TS2339: Property '_func' does not exist on type 'Alias'.
tests/cases/conformance/salsa/main.js(5,9): error TS2339: Property 'foo' does not exist on type 'Alias'.
tests/cases/conformance/salsa/main.js(6,9): error TS2339: Property 'func' does not exist on type 'Alias'.
==== tests/cases/conformance/salsa/mod1.js (0 errors) ====
@ -8,13 +11,21 @@ tests/cases/conformance/salsa/main.js(4,9): error TS2339: Property 'foo' does no
}
module.exports = Alias;
==== tests/cases/conformance/salsa/main.js (2 errors) ====
==== tests/cases/conformance/salsa/main.js (5 errors) ====
import A from './mod1'
A.prototype.foo = 0
~~~
!!! error TS2339: Property 'foo' does not exist on type 'Alias'.
A.prototype.func = function() { this._func = 0; }
~~~~
!!! error TS2339: Property 'func' does not exist on type 'Alias'.
~~~~~
!!! error TS2339: Property '_func' does not exist on type 'Alias'.
new A().bar
new A().foo
~~~
!!! error TS2339: Property 'foo' does not exist on type 'Alias'.
new A().func()
~~~~
!!! error TS2339: Property 'func' does not exist on type 'Alias'.

View file

@ -20,6 +20,12 @@ A.prototype.foo = 0
>A : Symbol(A, Decl(main.js, 0, 6))
>prototype : Symbol(A.prototype)
A.prototype.func = function() { this._func = 0; }
>A.prototype : Symbol(A.prototype)
>A : Symbol(A, Decl(main.js, 0, 6))
>prototype : Symbol(A.prototype)
>this : Symbol(A, Decl(mod1.js, 0, 0))
new A().bar
>new A().bar : Symbol(A.bar, Decl(mod1.js, 0, 13))
>A : Symbol(A, Decl(main.js, 0, 6))
@ -28,3 +34,6 @@ new A().bar
new A().foo
>A : Symbol(A, Decl(main.js, 0, 6))
new A().func()
>A : Symbol(A, Decl(main.js, 0, 6))

View file

@ -26,6 +26,20 @@ A.prototype.foo = 0
>foo : any
>0 : 0
A.prototype.func = function() { this._func = 0; }
>A.prototype.func = function() { this._func = 0; } : () => void
>A.prototype.func : any
>A.prototype : A
>A : typeof A
>prototype : A
>func : any
>function() { this._func = 0; } : () => void
>this._func = 0 : 0
>this._func : any
>this : A
>_func : any
>0 : 0
new A().bar
>new A().bar : () => number
>new A() : A
@ -38,3 +52,10 @@ new A().foo
>A : typeof A
>foo : any
new A().func()
>new A().func() : any
>new A().func : any
>new A() : A
>A : typeof A
>func : any

View file

@ -0,0 +1,23 @@
=== /a.js ===
function Graphic() {
>Graphic : Symbol(Graphic, Decl(a.js, 0, 0))
}
Object.defineProperty(Graphic.prototype, "instance", {
>Object.defineProperty : Symbol(ObjectConstructor.defineProperty, Decl(lib.es5.d.ts, --, --))
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>defineProperty : Symbol(ObjectConstructor.defineProperty, Decl(lib.es5.d.ts, --, --))
>Graphic.prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
>Graphic : Symbol(Graphic, Decl(a.js, 0, 0))
>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --))
>"instance" : Symbol(Graphic.instance, Decl(a.js, 1, 1))
get: function() {
>get : Symbol(get, Decl(a.js, 3, 54))
return this;
>this : Symbol(Graphic, Decl(a.js, 0, 0))
}
});

View file

@ -0,0 +1,26 @@
=== /a.js ===
function Graphic() {
>Graphic : typeof Graphic
}
Object.defineProperty(Graphic.prototype, "instance", {
>Object.defineProperty(Graphic.prototype, "instance", { get: function() { return this; }}) : any
>Object.defineProperty : (o: any, p: string | number | symbol, attributes: PropertyDescriptor & ThisType<any>) => any
>Object : ObjectConstructor
>defineProperty : (o: any, p: string | number | symbol, attributes: PropertyDescriptor & ThisType<any>) => any
>Graphic.prototype : any
>Graphic : typeof Graphic
>prototype : any
>"instance" : "instance"
>{ get: function() { return this; }} : { get: () => this; }
get: function() {
>get : () => this
>function() { return this; } : () => this
return this;
>this : this
}
});

View file

@ -0,0 +1,16 @@
/b.js(1,8): error TS1259: Module '"/a"' can only be default-imported using the 'esModuleInterop' flag
==== /a.js (0 errors) ====
// https://github.com/microsoft/TypeScript/issues/34481
const alias = {};
module.exports = alias;
==== /b.js (1 errors) ====
import a from "./a";
~
!!! error TS1259: Module '"/a"' can only be default-imported using the 'esModuleInterop' flag
!!! related TS2594 /a.js:5:1: This module is declared with using 'export =', and can only be used with a default import when using the 'esModuleInterop' flag.

View file

@ -0,0 +1,17 @@
=== /a.js ===
// https://github.com/microsoft/TypeScript/issues/34481
const alias = {};
>alias : Symbol(alias, Decl(a.js, 3, 5))
module.exports = alias;
>module.exports : Symbol("/a", Decl(a.js, 0, 0))
>module : Symbol(export=, Decl(a.js, 3, 17))
>exports : Symbol(export=, Decl(a.js, 3, 17))
>alias : Symbol(alias, Decl(a.js, 3, 5))
=== /b.js ===
import a from "./a";
>a : Symbol(a, Decl(b.js, 0, 6))

View file

@ -0,0 +1,19 @@
=== /a.js ===
// https://github.com/microsoft/TypeScript/issues/34481
const alias = {};
>alias : {}
>{} : {}
module.exports = alias;
>module.exports = alias : {}
>module.exports : {}
>module : { "/a": {}; }
>exports : {}
>alias : {}
=== /b.js ===
import a from "./a";
>a : any

View file

@ -0,0 +1,7 @@
=== tests/cases/compiler/jsNegativeELementAccessNotBound.js ===
var indexMap = {};
>indexMap : Symbol(indexMap, Decl(jsNegativeELementAccessNotBound.js, 0, 3))
indexMap[-1] = 0;
>indexMap : Symbol(indexMap, Decl(jsNegativeELementAccessNotBound.js, 0, 3))

View file

@ -0,0 +1,13 @@
=== tests/cases/compiler/jsNegativeELementAccessNotBound.js ===
var indexMap = {};
>indexMap : {}
>{} : {}
indexMap[-1] = 0;
>indexMap[-1] = 0 : 0
>indexMap[-1] : any
>indexMap : {}
>-1 : -1
>1 : 1
>0 : 0

View file

@ -0,0 +1,28 @@
=== tests/cases/conformance/jsdoc/mod1.js ===
class C {
>C : Symbol(C, Decl(mod1.js, 0, 0))
s() { }
>s : Symbol(C.s, Decl(mod1.js, 0, 9))
}
module.exports.C = C
>module.exports.C : Symbol(C, Decl(mod1.js, 2, 1))
>module.exports : Symbol(C, Decl(mod1.js, 2, 1))
>module : Symbol(module, Decl(mod1.js, 2, 1))
>exports : Symbol("tests/cases/conformance/jsdoc/mod1", Decl(mod1.js, 0, 0))
>C : Symbol(C, Decl(mod1.js, 2, 1))
>C : Symbol(C, Decl(mod1.js, 0, 0))
=== tests/cases/conformance/jsdoc/test.js ===
/** @typedef {import('./mod1').C} X */
/** @param {X} c */
function demo(c) {
>demo : Symbol(demo, Decl(test.js, 0, 0))
>c : Symbol(c, Decl(test.js, 2, 14))
c.s
>c.s : Symbol(C.s, Decl(mod1.js, 0, 9))
>c : Symbol(c, Decl(test.js, 2, 14))
>s : Symbol(C.s, Decl(mod1.js, 0, 9))
}

View file

@ -0,0 +1,29 @@
=== tests/cases/conformance/jsdoc/mod1.js ===
class C {
>C : C
s() { }
>s : () => void
}
module.exports.C = C
>module.exports.C = C : typeof C
>module.exports.C : typeof C
>module.exports : typeof import("tests/cases/conformance/jsdoc/mod1")
>module : { "tests/cases/conformance/jsdoc/mod1": typeof import("tests/cases/conformance/jsdoc/mod1"); }
>exports : typeof import("tests/cases/conformance/jsdoc/mod1")
>C : typeof C
>C : typeof C
=== tests/cases/conformance/jsdoc/test.js ===
/** @typedef {import('./mod1').C} X */
/** @param {X} c */
function demo(c) {
>demo : (c: C) => void
>c : C
c.s
>c.s : () => void
>c : C
>s : () => void
}

View file

@ -0,0 +1,32 @@
=== tests/cases/conformance/jsdoc/jsdocTypeReferenceToMergedClass.js ===
// https://github.com/microsoft/TypeScript/issues/34685
var Workspace = {}
>Workspace : Symbol(Workspace, Decl(jsdocTypeReferenceToMergedClass.js, 2, 3), Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 7, 37))
/** @type {Workspace.Project} */
var p;
>p : Symbol(p, Decl(jsdocTypeReferenceToMergedClass.js, 4, 3))
p.isServiceProject()
>p.isServiceProject : Symbol(isServiceProject, Decl(jsdocTypeReferenceToMergedClass.js, 8, 31))
>p : Symbol(p, Decl(jsdocTypeReferenceToMergedClass.js, 4, 3))
>isServiceProject : Symbol(isServiceProject, Decl(jsdocTypeReferenceToMergedClass.js, 8, 31))
Workspace.Project = function wp() { }
>Workspace.Project : Symbol(Workspace.Project, Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 8, 10))
>Workspace : Symbol(Workspace, Decl(jsdocTypeReferenceToMergedClass.js, 2, 3), Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 7, 37))
>Project : Symbol(Workspace.Project, Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 8, 10))
>wp : Symbol(wp, Decl(jsdocTypeReferenceToMergedClass.js, 7, 19))
Workspace.Project.prototype = {
>Workspace.Project.prototype : Symbol(Workspace.Project.prototype, Decl(jsdocTypeReferenceToMergedClass.js, 7, 37))
>Workspace.Project : Symbol(Workspace.Project, Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 8, 10))
>Workspace : Symbol(Workspace, Decl(jsdocTypeReferenceToMergedClass.js, 2, 3), Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 7, 37))
>Project : Symbol(Workspace.Project, Decl(jsdocTypeReferenceToMergedClass.js, 5, 20), Decl(jsdocTypeReferenceToMergedClass.js, 8, 10))
>prototype : Symbol(Workspace.Project.prototype, Decl(jsdocTypeReferenceToMergedClass.js, 7, 37))
isServiceProject() {}
>isServiceProject : Symbol(isServiceProject, Decl(jsdocTypeReferenceToMergedClass.js, 8, 31))
}

View file

@ -0,0 +1,38 @@
=== tests/cases/conformance/jsdoc/jsdocTypeReferenceToMergedClass.js ===
// https://github.com/microsoft/TypeScript/issues/34685
var Workspace = {}
>Workspace : typeof Workspace
>{} : {}
/** @type {Workspace.Project} */
var p;
>p : wp
p.isServiceProject()
>p.isServiceProject() : void
>p.isServiceProject : () => void
>p : wp
>isServiceProject : () => void
Workspace.Project = function wp() { }
>Workspace.Project = function wp() { } : typeof wp
>Workspace.Project : typeof wp
>Workspace : typeof Workspace
>Project : typeof wp
>function wp() { } : typeof wp
>wp : typeof wp
Workspace.Project.prototype = {
>Workspace.Project.prototype = { isServiceProject() {}} : { isServiceProject(): void; }
>Workspace.Project.prototype : { isServiceProject(): void; }
>Workspace.Project : typeof wp
>Workspace : typeof Workspace
>Project : typeof wp
>prototype : { isServiceProject(): void; }
>{ isServiceProject() {}} : { isServiceProject(): void; }
isServiceProject() {}
>isServiceProject : () => void
}

View file

@ -0,0 +1,10 @@
//// [mixedPropertyElementAccessAssignmentDeclaration.ts]
// Should not crash: #34642
var arr = [];
arr[0].prop[2] = {};
//// [mixedPropertyElementAccessAssignmentDeclaration.js]
// Should not crash: #34642
var arr = [];
arr[0].prop[2] = {};

View file

@ -0,0 +1,8 @@
=== tests/cases/conformance/salsa/mixedPropertyElementAccessAssignmentDeclaration.ts ===
// Should not crash: #34642
var arr = [];
>arr : Symbol(arr, Decl(mixedPropertyElementAccessAssignmentDeclaration.ts, 1, 3))
arr[0].prop[2] = {};
>arr : Symbol(arr, Decl(mixedPropertyElementAccessAssignmentDeclaration.ts, 1, 3))

View file

@ -0,0 +1,17 @@
=== tests/cases/conformance/salsa/mixedPropertyElementAccessAssignmentDeclaration.ts ===
// Should not crash: #34642
var arr = [];
>arr : any[]
>[] : undefined[]
arr[0].prop[2] = {};
>arr[0].prop[2] = {} : {}
>arr[0].prop[2] : any
>arr[0].prop : any
>arr[0] : any
>arr : any[]
>0 : 0
>prop : any
>2 : 2
>{} : {}

View file

@ -38,10 +38,36 @@ const cc4 = c4 ?? true;
const dd1 = d1 ?? {b: 1};
const dd2 = d2 ?? {b: 1};
const dd3 = d3 ?? {b: 1};
const dd4 = d4 ?? {b: 1};
const dd4 = d4 ?? {b: 1};
// Repro from #34635
declare function foo(): void;
const maybeBool = false;
if (!(maybeBool ?? true)) {
foo();
}
if (maybeBool ?? true) {
foo();
}
else {
foo();
}
if (false ?? true) {
foo();
}
else {
foo();
}
//// [nullishCoalescingOperator1.js]
"use strict";
var _a;
var aa1 = (a1 !== null && a1 !== void 0 ? a1 : 'whatever');
var aa2 = (a2 !== null && a2 !== void 0 ? a2 : 'whatever');
var aa3 = (a3 !== null && a3 !== void 0 ? a3 : 'whatever');
@ -58,3 +84,19 @@ var dd1 = (d1 !== null && d1 !== void 0 ? d1 : { b: 1 });
var dd2 = (d2 !== null && d2 !== void 0 ? d2 : { b: 1 });
var dd3 = (d3 !== null && d3 !== void 0 ? d3 : { b: 1 });
var dd4 = (d4 !== null && d4 !== void 0 ? d4 : { b: 1 });
var maybeBool = false;
if (!((maybeBool !== null && maybeBool !== void 0 ? maybeBool : true))) {
foo();
}
if ((maybeBool !== null && maybeBool !== void 0 ? maybeBool : true)) {
foo();
}
else {
foo();
}
if (_a = false, (_a !== null && _a !== void 0 ? _a : true)) {
foo();
}
else {
foo();
}

View file

@ -123,3 +123,38 @@ const dd4 = d4 ?? {b: 1};
>d4 : Symbol(d4, Decl(nullishCoalescingOperator1.ts, 19, 13))
>b : Symbol(b, Decl(nullishCoalescingOperator1.ts, 39, 19))
// Repro from #34635
declare function foo(): void;
>foo : Symbol(foo, Decl(nullishCoalescingOperator1.ts, 39, 25))
const maybeBool = false;
>maybeBool : Symbol(maybeBool, Decl(nullishCoalescingOperator1.ts, 45, 5))
if (!(maybeBool ?? true)) {
>maybeBool : Symbol(maybeBool, Decl(nullishCoalescingOperator1.ts, 45, 5))
foo();
>foo : Symbol(foo, Decl(nullishCoalescingOperator1.ts, 39, 25))
}
if (maybeBool ?? true) {
>maybeBool : Symbol(maybeBool, Decl(nullishCoalescingOperator1.ts, 45, 5))
foo();
>foo : Symbol(foo, Decl(nullishCoalescingOperator1.ts, 39, 25))
}
else {
foo();
>foo : Symbol(foo, Decl(nullishCoalescingOperator1.ts, 39, 25))
}
if (false ?? true) {
foo();
>foo : Symbol(foo, Decl(nullishCoalescingOperator1.ts, 39, 25))
}
else {
foo();
>foo : Symbol(foo, Decl(nullishCoalescingOperator1.ts, 39, 25))
}

View file

@ -170,3 +170,54 @@ const dd4 = d4 ?? {b: 1};
>b : number
>1 : 1
// Repro from #34635
declare function foo(): void;
>foo : () => void
const maybeBool = false;
>maybeBool : false
>false : false
if (!(maybeBool ?? true)) {
>!(maybeBool ?? true) : true
>(maybeBool ?? true) : false
>maybeBool ?? true : false
>maybeBool : false
>true : true
foo();
>foo() : void
>foo : () => void
}
if (maybeBool ?? true) {
>maybeBool ?? true : false
>maybeBool : false
>true : true
foo();
>foo() : void
>foo : () => void
}
else {
foo();
>foo() : void
>foo : () => void
}
if (false ?? true) {
>false ?? true : false
>false : false
>true : true
foo();
>foo() : void
>foo : () => void
}
else {
foo();
>foo() : void
>foo : () => void
}

View file

@ -52,10 +52,43 @@ let y1 = foo1(sx); // string
let x2 = foo2(sa); // unknown
let y2 = foo2(sx); // { extra: number }
// Repro from #33490
declare class Component<P> { props: P }
export type ComponentClass<P> = new (props: P) => Component<P>;
export type FunctionComponent<P> = (props: P) => null;
export type ComponentType<P> = FunctionComponent<P> | ComponentClass<P>;
export interface RouteComponentProps { route: string }
declare function withRouter<
P extends RouteComponentProps,
C extends ComponentType<P>
>(
component: C & ComponentType<P>
): ComponentClass<Omit<P, keyof RouteComponentProps>>;
interface Props extends RouteComponentProps { username: string }
declare const MyComponent: ComponentType<Props>;
withRouter(MyComponent);
// Repro from #33490
type AB<T> = { a: T } | { b: T };
// T & AB<U> normalizes to T & { a: U } | T & { b: U } below
declare function foo<T, U>(obj: T & AB<U>): [T, U];
declare let ab: AB<string>;
let z = foo(ab); // [AB<string>, string]
//// [unionAndIntersectionInference3.js]
"use strict";
// Repro from #30720
concatMaybe([1, 2, 3], 4);
// Repros from #32247
@ -70,3 +103,5 @@ let x1 = foo1(sa); // string
let y1 = foo1(sx); // string
let x2 = foo2(sa); // unknown
let y2 = foo2(sx); // { extra: number }
withRouter(MyComponent);
let z = foo(ab); // [AB<string>, string]

View file

@ -205,3 +205,107 @@ let y2 = foo2(sx); // { extra: number }
>foo2 : Symbol(foo2, Decl(unionAndIntersectionInference3.ts, 42, 57))
>sx : Symbol(sx, Decl(unionAndIntersectionInference3.ts, 46, 11))
// Repro from #33490
declare class Component<P> { props: P }
>Component : Symbol(Component, Decl(unionAndIntersectionInference3.ts, 52, 18))
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 56, 24))
>props : Symbol(Component.props, Decl(unionAndIntersectionInference3.ts, 56, 28))
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 56, 24))
export type ComponentClass<P> = new (props: P) => Component<P>;
>ComponentClass : Symbol(ComponentClass, Decl(unionAndIntersectionInference3.ts, 56, 39))
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 58, 27))
>props : Symbol(props, Decl(unionAndIntersectionInference3.ts, 58, 37))
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 58, 27))
>Component : Symbol(Component, Decl(unionAndIntersectionInference3.ts, 52, 18))
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 58, 27))
export type FunctionComponent<P> = (props: P) => null;
>FunctionComponent : Symbol(FunctionComponent, Decl(unionAndIntersectionInference3.ts, 58, 63))
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 59, 30))
>props : Symbol(props, Decl(unionAndIntersectionInference3.ts, 59, 36))
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 59, 30))
export type ComponentType<P> = FunctionComponent<P> | ComponentClass<P>;
>ComponentType : Symbol(ComponentType, Decl(unionAndIntersectionInference3.ts, 59, 54))
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 61, 26))
>FunctionComponent : Symbol(FunctionComponent, Decl(unionAndIntersectionInference3.ts, 58, 63))
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 61, 26))
>ComponentClass : Symbol(ComponentClass, Decl(unionAndIntersectionInference3.ts, 56, 39))
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 61, 26))
export interface RouteComponentProps { route: string }
>RouteComponentProps : Symbol(RouteComponentProps, Decl(unionAndIntersectionInference3.ts, 61, 72))
>route : Symbol(RouteComponentProps.route, Decl(unionAndIntersectionInference3.ts, 63, 38))
declare function withRouter<
>withRouter : Symbol(withRouter, Decl(unionAndIntersectionInference3.ts, 63, 54))
P extends RouteComponentProps,
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 65, 28))
>RouteComponentProps : Symbol(RouteComponentProps, Decl(unionAndIntersectionInference3.ts, 61, 72))
C extends ComponentType<P>
>C : Symbol(C, Decl(unionAndIntersectionInference3.ts, 66, 32))
>ComponentType : Symbol(ComponentType, Decl(unionAndIntersectionInference3.ts, 59, 54))
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 65, 28))
>(
component: C & ComponentType<P>
>component : Symbol(component, Decl(unionAndIntersectionInference3.ts, 68, 2))
>C : Symbol(C, Decl(unionAndIntersectionInference3.ts, 66, 32))
>ComponentType : Symbol(ComponentType, Decl(unionAndIntersectionInference3.ts, 59, 54))
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 65, 28))
): ComponentClass<Omit<P, keyof RouteComponentProps>>;
>ComponentClass : Symbol(ComponentClass, Decl(unionAndIntersectionInference3.ts, 56, 39))
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
>P : Symbol(P, Decl(unionAndIntersectionInference3.ts, 65, 28))
>RouteComponentProps : Symbol(RouteComponentProps, Decl(unionAndIntersectionInference3.ts, 61, 72))
interface Props extends RouteComponentProps { username: string }
>Props : Symbol(Props, Decl(unionAndIntersectionInference3.ts, 70, 54))
>RouteComponentProps : Symbol(RouteComponentProps, Decl(unionAndIntersectionInference3.ts, 61, 72))
>username : Symbol(Props.username, Decl(unionAndIntersectionInference3.ts, 72, 45))
declare const MyComponent: ComponentType<Props>;
>MyComponent : Symbol(MyComponent, Decl(unionAndIntersectionInference3.ts, 74, 13))
>ComponentType : Symbol(ComponentType, Decl(unionAndIntersectionInference3.ts, 59, 54))
>Props : Symbol(Props, Decl(unionAndIntersectionInference3.ts, 70, 54))
withRouter(MyComponent);
>withRouter : Symbol(withRouter, Decl(unionAndIntersectionInference3.ts, 63, 54))
>MyComponent : Symbol(MyComponent, Decl(unionAndIntersectionInference3.ts, 74, 13))
// Repro from #33490
type AB<T> = { a: T } | { b: T };
>AB : Symbol(AB, Decl(unionAndIntersectionInference3.ts, 76, 24))
>T : Symbol(T, Decl(unionAndIntersectionInference3.ts, 80, 8))
>a : Symbol(a, Decl(unionAndIntersectionInference3.ts, 80, 14))
>T : Symbol(T, Decl(unionAndIntersectionInference3.ts, 80, 8))
>b : Symbol(b, Decl(unionAndIntersectionInference3.ts, 80, 25))
>T : Symbol(T, Decl(unionAndIntersectionInference3.ts, 80, 8))
// T & AB<U> normalizes to T & { a: U } | T & { b: U } below
declare function foo<T, U>(obj: T & AB<U>): [T, U];
>foo : Symbol(foo, Decl(unionAndIntersectionInference3.ts, 80, 33))
>T : Symbol(T, Decl(unionAndIntersectionInference3.ts, 83, 21))
>U : Symbol(U, Decl(unionAndIntersectionInference3.ts, 83, 23))
>obj : Symbol(obj, Decl(unionAndIntersectionInference3.ts, 83, 27))
>T : Symbol(T, Decl(unionAndIntersectionInference3.ts, 83, 21))
>AB : Symbol(AB, Decl(unionAndIntersectionInference3.ts, 76, 24))
>U : Symbol(U, Decl(unionAndIntersectionInference3.ts, 83, 23))
>T : Symbol(T, Decl(unionAndIntersectionInference3.ts, 83, 21))
>U : Symbol(U, Decl(unionAndIntersectionInference3.ts, 83, 23))
declare let ab: AB<string>;
>ab : Symbol(ab, Decl(unionAndIntersectionInference3.ts, 84, 11))
>AB : Symbol(AB, Decl(unionAndIntersectionInference3.ts, 76, 24))
let z = foo(ab); // [AB<string>, string]
>z : Symbol(z, Decl(unionAndIntersectionInference3.ts, 86, 3))
>foo : Symbol(foo, Decl(unionAndIntersectionInference3.ts, 80, 33))
>ab : Symbol(ab, Decl(unionAndIntersectionInference3.ts, 84, 11))

View file

@ -135,3 +135,67 @@ let y2 = foo2(sx); // { extra: number }
>foo2 : <T>(obj: string[] & T) => T
>sx : string[] & { extra: number; }
// Repro from #33490
declare class Component<P> { props: P }
>Component : Component<P>
>props : P
export type ComponentClass<P> = new (props: P) => Component<P>;
>ComponentClass : ComponentClass<P>
>props : P
export type FunctionComponent<P> = (props: P) => null;
>FunctionComponent : FunctionComponent<P>
>props : P
>null : null
export type ComponentType<P> = FunctionComponent<P> | ComponentClass<P>;
>ComponentType : ComponentType<P>
export interface RouteComponentProps { route: string }
>route : string
declare function withRouter<
>withRouter : <P extends RouteComponentProps, C extends ComponentType<P>>(component: (C & FunctionComponent<P>) | (C & ComponentClass<P>)) => ComponentClass<Pick<P, Exclude<keyof P, "route">>>
P extends RouteComponentProps,
C extends ComponentType<P>
>(
component: C & ComponentType<P>
>component : (C & FunctionComponent<P>) | (C & ComponentClass<P>)
): ComponentClass<Omit<P, keyof RouteComponentProps>>;
interface Props extends RouteComponentProps { username: string }
>username : string
declare const MyComponent: ComponentType<Props>;
>MyComponent : ComponentType<Props>
withRouter(MyComponent);
>withRouter(MyComponent) : ComponentClass<Pick<Props, "username">>
>withRouter : <P extends RouteComponentProps, C extends ComponentType<P>>(component: (C & FunctionComponent<P>) | (C & ComponentClass<P>)) => ComponentClass<Pick<P, Exclude<keyof P, "route">>>
>MyComponent : ComponentType<Props>
// Repro from #33490
type AB<T> = { a: T } | { b: T };
>AB : AB<T>
>a : T
>b : T
// T & AB<U> normalizes to T & { a: U } | T & { b: U } below
declare function foo<T, U>(obj: T & AB<U>): [T, U];
>foo : <T, U>(obj: (T & { a: U; }) | (T & { b: U; })) => [T, U]
>obj : (T & { a: U; }) | (T & { b: U; })
declare let ab: AB<string>;
>ab : AB<string>
let z = foo(ab); // [AB<string>, string]
>z : [AB<string>, string]
>foo(ab) : [AB<string>, string]
>foo : <T, U>(obj: (T & { a: U; }) | (T & { b: U; })) => [T, U]
>ab : AB<string>

View file

@ -0,0 +1,34 @@
// @declaration: true
// @filename: wrapClass.ts
export function wrapClass(param: any) {
return class Wrapped {
foo() {
return param;
}
}
}
export type Constructor<T = {}> = new (...args: any[]) => T;
export function Timestamped<TBase extends Constructor>(Base: TBase) {
return class extends Base {
timestamp = Date.now();
};
}
// @filename: index.ts
import { wrapClass, Timestamped } from "./wrapClass";
export default wrapClass(0);
// Simple class
export class User {
name = '';
}
// User that is Timestamped
export class TimestampedUser extends Timestamped(User) {
constructor() {
super();
}
}

View file

@ -0,0 +1,14 @@
// @allowJs: true
// @checkJs: false
// @noEmit: true
// @Filename: /a.js
function Graphic() {
}
Object.defineProperty(Graphic.prototype, "instance", {
get: function() {
return this;
}
});

View file

@ -0,0 +1,12 @@
// https://github.com/microsoft/TypeScript/issues/34481
// @allowJs: true
// @checkJs: true
// @noEmit: true
// @Filename: /a.js
const alias = {};
module.exports = alias;
// @Filename: /b.js
import a from "./a";

View file

@ -0,0 +1,6 @@
// @allowJs: true
// @checkJs: true
// @noEmit: true
// @filename: jsNegativeELementAccessNotBound.js
var indexMap = {};
indexMap[-1] = 0;

View file

@ -302,6 +302,60 @@ function f14(o: Thing | null) {
}
}
function f15(o: Thing | undefined, value: number) {
if (o?.foo === value) {
o.foo;
}
else {
o.foo; // Error
}
if (o?.foo !== value) {
o.foo; // Error
}
else {
o.foo;
}
if (o?.foo == value) {
o.foo;
}
else {
o.foo; // Error
}
if (o?.foo != value) {
o.foo; // Error
}
else {
o.foo;
}
}
function f16(o: Thing | undefined) {
if (o?.foo === undefined) {
o.foo; // Error
}
else {
o.foo;
}
if (o?.foo !== undefined) {
o.foo;
}
else {
o.foo; // Error
}
if (o?.foo == undefined) {
o.foo; // Error
}
else {
o.foo;
}
if (o?.foo != undefined) {
o.foo;
}
else {
o.foo; // Error
}
}
function f20(o: Thing | undefined) {
if (typeof o?.foo === "number") {
o.foo;
@ -331,3 +385,146 @@ function f21(o: Thing | null) {
o.baz;
}
}
function f22(o: Thing | undefined) {
if (typeof o?.foo === "number") {
o.foo;
}
else {
o.foo; // Error
}
if (typeof o?.foo !== "number") {
o.foo; // Error
}
else {
o.foo;
}
if (typeof o?.foo == "number") {
o.foo;
}
else {
o.foo; // Error
}
if (typeof o?.foo != "number") {
o.foo; // Error
}
else {
o.foo;
}
}
function f23(o: Thing | undefined) {
if (typeof o?.foo === "undefined") {
o.foo; // Error
}
else {
o.foo;
}
if (typeof o?.foo !== "undefined") {
o.foo;
}
else {
o.foo; // Error
}
if (typeof o?.foo == "undefined") {
o.foo; // Error
}
else {
o.foo;
}
if (typeof o?.foo != "undefined") {
o.foo;
}
else {
o.foo; // Error
}
}
declare function assert(x: unknown): asserts x;
declare function assertNonNull<T>(x: T): asserts x is NonNullable<T>;
function f30(o: Thing | undefined) {
if (!!true) {
assert(o?.foo);
o.foo;
}
if (!!true) {
assert(o?.foo === 42);
o.foo;
}
if (!!true) {
assert(typeof o?.foo === "number");
o.foo;
}
if (!!true) {
assertNonNull(o?.foo);
o.foo;
}
}
function f40(o: Thing | undefined) {
switch (o?.foo) {
case "abc":
o.foo;
break;
case 42:
o.foo;
break;
case undefined:
o.foo; // Error
break;
default:
o.foo; // Error
break;
}
}
function f41(o: Thing | undefined) {
switch (typeof o?.foo) {
case "string":
o.foo;
break;
case "number":
o.foo;
break;
case "undefined":
o.foo; // Error
break;
default:
o.foo; // Error
break;
}
}
// Repros from #34570
type Shape =
| { type: 'rectangle', width: number, height: number }
| { type: 'circle', radius: number }
function getArea(shape?: Shape) {
switch (shape?.type) {
case 'circle':
return Math.PI * shape.radius ** 2
case 'rectangle':
return shape.width * shape.height
default:
return 0
}
}
type Feature = {
id: string;
geometry?: {
type: string;
coordinates: number[];
};
};
function extractCoordinates(f: Feature): number[] {
if (f.geometry?.type !== 'test') {
return [];
}
return f.geometry.coordinates;
}

View file

@ -1,4 +1,5 @@
// @strict: true
// @allowUnreachableCode: false
declare const a1: string | undefined | null
declare const a2: string | undefined | null
@ -39,4 +40,28 @@ const cc4 = c4 ?? true;
const dd1 = d1 ?? {b: 1};
const dd2 = d2 ?? {b: 1};
const dd3 = d3 ?? {b: 1};
const dd4 = d4 ?? {b: 1};
const dd4 = d4 ?? {b: 1};
// Repro from #34635
declare function foo(): void;
const maybeBool = false;
if (!(maybeBool ?? true)) {
foo();
}
if (maybeBool ?? true) {
foo();
}
else {
foo();
}
if (false ?? true) {
foo();
}
else {
foo();
}

View file

@ -0,0 +1,11 @@
// @allowJs: true
// @checkJs: true
// @noEmit: true
// @Filename: callOfPropertylessConstructorFunction.js
/**
* @constructor
*/
function Dependency(j) {
return j
}
Dependency({})

View file

@ -0,0 +1,15 @@
// @allowJS: true
// @suppressOutputPathCheck: true
// @filename: 0.js
// @ts-check
var exports = {};
/**
* @typedef {string}
*/
exports.SomeName;
/** @type {exports.SomeName} */
const myString = 'str';

View file

@ -0,0 +1,15 @@
// @noEmit: true
// @allowJs: true
// @checkJs: true
// @Filename: mod1.js
class C {
s() { }
}
module.exports.C = C
// @Filename: test.js
/** @typedef {import('./mod1').C} X */
/** @param {X} c */
function demo(c) {
c.s
}

View file

@ -0,0 +1,15 @@
// https://github.com/microsoft/TypeScript/issues/34685
// @noEmit: true
// @allowJs: true
// @checkJs: true
// @Filename: jsdocTypeReferenceToMergedClass.js
var Workspace = {}
/** @type {Workspace.Project} */
var p;
p.isServiceProject()
Workspace.Project = function wp() { }
Workspace.Project.prototype = {
isServiceProject() {}
}

View file

@ -11,5 +11,7 @@ module.exports = Alias;
// @filename: main.js
import A from './mod1'
A.prototype.foo = 0
A.prototype.func = function() { this._func = 0; }
new A().bar
new A().foo
new A().func()

View file

@ -0,0 +1,3 @@
// Should not crash: #34642
var arr = [];
arr[0].prop[2] = {};

View file

@ -54,3 +54,37 @@ let y1 = foo1(sx); // string
let x2 = foo2(sa); // unknown
let y2 = foo2(sx); // { extra: number }
// Repro from #33490
declare class Component<P> { props: P }
export type ComponentClass<P> = new (props: P) => Component<P>;
export type FunctionComponent<P> = (props: P) => null;
export type ComponentType<P> = FunctionComponent<P> | ComponentClass<P>;
export interface RouteComponentProps { route: string }
declare function withRouter<
P extends RouteComponentProps,
C extends ComponentType<P>
>(
component: C & ComponentType<P>
): ComponentClass<Omit<P, keyof RouteComponentProps>>;
interface Props extends RouteComponentProps { username: string }
declare const MyComponent: ComponentType<Props>;
withRouter(MyComponent);
// Repro from #33490
type AB<T> = { a: T } | { b: T };
// T & AB<U> normalizes to T & { a: U } | T & { b: U } below
declare function foo<T, U>(obj: T & AB<U>): [T, U];
declare let ab: AB<string>;
let z = foo(ab); // [AB<string>, string]

View file

@ -0,0 +1,20 @@
/// <reference path="fourslash.ts" />
// @strict: true
//// interface User {
//// address?: {
//// city: string;
//// "postal code": string;
//// }
//// };
//// declare const user: User;
//// user.address[|./**/|]
verify.completions({
marker: "",
exact: [],
preferences: {
includeInsertTextCompletions: true,
includeAutomaticOptionalChainCompletions: false
},
});

View file

@ -0,0 +1,8 @@
/// <reference path='fourslash.ts' />
// @noLib: true
////[|this|];
////export const c = 1;
const [glob] = test.ranges();
verify.referenceGroups(glob, undefined);

View file

@ -583,6 +583,7 @@ declare namespace FourSlashInterface {
readonly quotePreference?: "double" | "single";
readonly includeCompletionsForModuleExports?: boolean;
readonly includeInsertTextCompletions?: boolean;
readonly includeAutomaticOptionalChainCompletions?: boolean;
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
readonly importModuleSpecifierEnding?: "minimal" | "index" | "js";
}

View file

@ -0,0 +1,57 @@
/// <reference path="fourslash.ts"/>
////function F(key, value) {
//// return {
//// [key]: value,
//// "prop": true
//// }
////}
verify.navigationTree({
"text": "<global>",
"kind": "script",
"childItems": [
{
"text": "F",
"kind": "function",
"childItems": [
{
"text": "[key]",
"kind": "property"
},
{
"text": "\"prop\"",
"kind": "property"
}
]
}
]
});
verify.navigationBar([
{
"text": "<global>",
"kind": "script",
"childItems": [
{
"text": "F",
"kind": "function"
}
]
},
{
"text": "F",
"kind": "function",
"childItems": [
{
"text": "[key]",
"kind": "property"
},
{
"text": "\"prop\"",
"kind": "property"
}
],
"indent": 1
}
]);