diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index c1b0aabbf9d..2454a36cb57 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -1,4 +1,4 @@
-///
+///
///
/* @internal */
@@ -3737,11 +3737,16 @@ namespace ts {
return getObjectFlags(type) & ObjectFlags.Reference ? (type).target : type;
}
- function hasBaseType(type: InterfaceType, checkBase: InterfaceType) {
+ function hasBaseType(type: BaseType, checkBase: BaseType) {
return check(type);
- function check(type: InterfaceType): boolean {
- const target = getTargetType(type);
- return target === checkBase || forEach(getBaseTypes(target), check);
+ function check(type: BaseType): boolean {
+ if (getObjectFlags(type) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) {
+ const target = getTargetType(type);
+ return target === checkBase || forEach(getBaseTypes(target), check);
+ }
+ else if (type.flags & TypeFlags.Intersection) {
+ return forEach((type).types, check);
+ }
}
}
@@ -3810,7 +3815,7 @@ namespace ts {
}
function isConstructorType(type: Type): boolean {
- return type.flags & TypeFlags.Object && getSignaturesOfType(type, SignatureKind.Construct).length > 0;
+ return isValidBaseType(type) && getSignaturesOfType(type, SignatureKind.Construct).length > 0;
}
function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments {
@@ -3849,7 +3854,7 @@ namespace ts {
return unknownType;
}
const baseConstructorType = checkExpression(baseTypeNode.expression);
- if (baseConstructorType.flags & TypeFlags.Object) {
+ if (baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection)) {
// Resolving the members of a class requires us to resolve the base class of that class.
// We force resolution here such that we catch circularities now.
resolveStructuredTypeMembers(baseConstructorType);
@@ -3867,7 +3872,7 @@ namespace ts {
return type.resolvedBaseConstructorType;
}
- function getBaseTypes(type: InterfaceType): ObjectType[] {
+ function getBaseTypes(type: InterfaceType): BaseType[] {
if (!type.resolvedBaseTypes) {
if (type.objectFlags & ObjectFlags.Tuple) {
type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters))];
@@ -3890,7 +3895,7 @@ namespace ts {
function resolveBaseTypesOfClass(type: InterfaceType): void {
type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray;
const baseConstructorType = getBaseConstructorTypeOfClass(type);
- if (!(baseConstructorType.flags & TypeFlags.Object)) {
+ if (!(baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection))) {
return;
}
const baseTypeNode = getBaseTypeNodeOfClass(type);
@@ -3927,11 +3932,11 @@ namespace ts {
if (baseType === unknownType) {
return;
}
- if (!(getObjectFlags(getTargetType(baseType)) & ObjectFlags.ClassOrInterface)) {
+ if (!isValidBaseType(baseType)) {
error(baseTypeNode.expression, Diagnostics.Base_constructor_return_type_0_is_not_a_class_or_interface_type, typeToString(baseType));
return;
}
- if (type === baseType || hasBaseType(baseType, type)) {
+ if (type === baseType || hasBaseType(baseType, type)) {
error(valueDecl, Diagnostics.Type_0_recursively_references_itself_as_a_base_type,
typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
return;
@@ -3956,6 +3961,13 @@ namespace ts {
return true;
}
+ // A valid base type is any non-generic object type or intersection of non-generic
+ // object types.
+ function isValidBaseType(type: Type): boolean {
+ return type.flags & TypeFlags.Object && !isGenericMappedType(type) ||
+ type.flags & TypeFlags.Intersection && !forEach((type).types, t => !isValidBaseType(t));
+ }
+
function resolveBaseTypesOfInterface(type: InterfaceType): void {
type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray;
for (const declaration of type.symbol.declarations) {
@@ -3963,8 +3975,8 @@ namespace ts {
for (const node of getInterfaceBaseTypeNodes(declaration)) {
const baseType = getTypeFromTypeNode(node);
if (baseType !== unknownType) {
- if (getObjectFlags(getTargetType(baseType)) & ObjectFlags.ClassOrInterface) {
- if (type !== baseType && !hasBaseType(baseType, type)) {
+ if (isValidBaseType(baseType)) {
+ if (type !== baseType && !hasBaseType(baseType, type)) {
if (type.resolvedBaseTypes === emptyArray) {
type.resolvedBaseTypes = [baseType];
}
@@ -4177,7 +4189,6 @@ namespace ts {
}
function getDeclaredTypeOfSymbol(symbol: Symbol): Type {
- Debug.assert((symbol.flags & SymbolFlags.Instantiated) === 0);
if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
return getDeclaredTypeOfClassOrInterface(symbol);
}
@@ -4319,8 +4330,14 @@ namespace ts {
function getTypeWithThisArgument(type: Type, thisArgument?: Type): Type {
if (getObjectFlags(type) & ObjectFlags.Reference) {
- return createTypeReference((type).target,
- concatenate((type).typeArguments, [thisArgument || (type).target.thisType]));
+ const target = (type).target;
+ const typeArguments = (type).typeArguments;
+ if (length(target.typeParameters) === length(typeArguments)) {
+ return createTypeReference(target, concatenate(typeArguments, [thisArgument || target.thisType]));
+ }
+ }
+ else if (type.flags & TypeFlags.Intersection) {
+ return getIntersectionType(map((type).types, t => getTypeWithThisArgument(t, thisArgument)));
}
return type;
}
@@ -4355,8 +4372,8 @@ namespace ts {
}
const thisArgument = lastOrUndefined(typeArguments);
for (const baseType of baseTypes) {
- const instantiatedBaseType = thisArgument ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType;
- addInheritedMembers(members, getPropertiesOfObjectType(instantiatedBaseType));
+ const instantiatedBaseType = thisArgument ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType;
+ addInheritedMembers(members, getPropertiesOfType(instantiatedBaseType));
callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call));
constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct));
stringIndexInfo = stringIndexInfo || getIndexInfoOfType(instantiatedBaseType, IndexKind.String);
@@ -4578,9 +4595,9 @@ namespace ts {
constructSignatures = getDefaultConstructSignatures(classType);
}
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
- if (baseConstructorType.flags & TypeFlags.Object) {
+ if (baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection)) {
members = createSymbolTable(getNamedMembers(members));
- addInheritedMembers(members, getPropertiesOfObjectType(baseConstructorType));
+ addInheritedMembers(members, getPropertiesOfType(baseConstructorType));
}
}
const numberIndexInfo = symbol.flags & SymbolFlags.Enum ? enumNumberIndexInfo : undefined;
@@ -4606,12 +4623,14 @@ namespace ts {
const typeParameter = getTypeParameterFromMappedType(type);
const constraintType = getConstraintTypeFromMappedType(type);
const templateType = getTemplateTypeFromMappedType(type);
- const modifiersType = getApparentType(getModifiersTypeFromMappedType(type));
+ const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
const templateReadonly = !!type.declaration.readonlyToken;
const templateOptional = !!type.declaration.questionToken;
if (type.declaration.typeParameter.constraint.kind === SyntaxKind.TypeOperator) {
// We have a { [P in keyof T]: X }
- forEachType(getLiteralTypeFromPropertyNames(modifiersType), addMemberForKeyType);
+ for (const propertySymbol of getPropertiesOfType(modifiersType)) {
+ addMemberForKeyType(getLiteralTypeFromPropertyName(propertySymbol), propertySymbol);
+ }
if (getIndexInfoOfType(modifiersType, IndexKind.String)) {
addMemberForKeyType(stringType);
}
@@ -4626,7 +4645,7 @@ namespace ts {
}
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined);
- function addMemberForKeyType(t: Type) {
+ function addMemberForKeyType(t: Type, propertySymbol?: Symbol) {
// Create a mapper from T to the current iteration type constituent. Then, if the
// mapped type is itself an instantiated type, combine the iteration mapper with the
// instantiation mapper.
@@ -4642,6 +4661,9 @@ namespace ts {
const prop = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | (isOptional ? SymbolFlags.Optional : 0), propName);
prop.type = propType;
prop.isReadonly = templateReadonly || modifiersProp && isReadonlySymbol(modifiersProp);
+ if (propertySymbol) {
+ prop.mappedTypeOrigin = propertySymbol;
+ }
members.set(propName, prop);
}
else if (t.flags & TypeFlags.String) {
@@ -4744,28 +4766,26 @@ namespace ts {
}
function getPropertiesOfUnionOrIntersectionType(type: UnionOrIntersectionType): Symbol[] {
- for (const current of type.types) {
- for (const prop of getPropertiesOfType(current)) {
- getUnionOrIntersectionProperty(type, prop.name);
- }
- // The properties of a union type are those that are present in all constituent types, so
- // we only need to check the properties of the first type
- if (type.flags & TypeFlags.Union) {
- break;
- }
- }
- const props = type.resolvedProperties;
- if (props) {
- const result: Symbol[] = [];
- props.forEach(prop => {
- // We need to filter out partial properties in union types
- if (!(prop.flags & SymbolFlags.SyntheticProperty && (prop).isPartial)) {
- result.push(prop);
+ if (!type.resolvedProperties) {
+ const members = createMap();
+ for (const current of type.types) {
+ for (const prop of getPropertiesOfType(current)) {
+ if (!members.has(prop.name)) {
+ const combinedProp = getPropertyOfUnionOrIntersectionType(type, prop.name);
+ if (combinedProp) {
+ members.set(prop.name, combinedProp);
+ }
+ }
}
- });
- return result;
+ // The properties of a union type are those that are present in all constituent types, so
+ // we only need to check the properties of the first type
+ if (type.flags & TypeFlags.Union) {
+ break;
+ }
+ }
+ type.resolvedProperties = getNamedMembers(members);
}
- return emptyArray;
+ return type.resolvedProperties;
}
function getPropertiesOfType(type: Type): Symbol[] {
@@ -4850,6 +4870,10 @@ namespace ts {
}
}
+ function getApparentTypeOfIntersectionType(type: IntersectionType) {
+ return type.resolvedIndexType || (type.resolvedApparentType = getTypeWithThisArgument(type, type));
+ }
+
/**
* For a type parameter, return the base constraint of the type parameter. For the string, number,
* boolean, and symbol primitive types, return the corresponding object types. Otherwise return the
@@ -4857,7 +4881,8 @@ namespace ts {
*/
function getApparentType(type: Type): Type {
const t = type.flags & TypeFlags.TypeVariable ? getBaseConstraintOfType(type) || emptyObjectType : type;
- return t.flags & TypeFlags.StringLike ? globalStringType :
+ return t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(t) :
+ t.flags & TypeFlags.StringLike ? globalStringType :
t.flags & TypeFlags.NumberLike ? globalNumberType :
t.flags & TypeFlags.BooleanLike ? globalBooleanType :
t.flags & TypeFlags.ESSymbol ? getGlobalESSymbolType() :
@@ -4933,7 +4958,7 @@ namespace ts {
// these partial properties when identifying discriminant properties, but otherwise they are filtered out
// and do not appear to be present in the union type.
function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: string): Symbol {
- const properties = type.resolvedProperties || (type.resolvedProperties = createMap());
+ const properties = type.propertyCache || (type.propertyCache = createMap());
let property = properties.get(name);
if (!property) {
property = createUnionOrIntersectionProperty(type, name);
@@ -6296,6 +6321,9 @@ namespace ts {
if (right.flags & TypeFlags.Union) {
return mapType(right, t => getSpreadType(left, t));
}
+ if (right.flags & TypeFlags.NonPrimitive) {
+ return emptyObjectType;
+ }
const members = createMap();
const skippedPrivateMembers = createMap();
@@ -11812,7 +11840,7 @@ namespace ts {
}
function isValidSpreadType(type: Type): boolean {
- return !!(type.flags & (TypeFlags.Any | TypeFlags.Null | TypeFlags.Undefined) ||
+ return !!(type.flags & (TypeFlags.Any | TypeFlags.Null | TypeFlags.Undefined | TypeFlags.NonPrimitive) ||
type.flags & TypeFlags.Object && !isGenericMappedType(type) ||
type.flags & TypeFlags.UnionOrIntersection && !forEach((type).types, t => !isValidSpreadType(t)));
}
@@ -16067,12 +16095,12 @@ namespace ts {
}
}
- /**
+ /**
* Static members being set on a constructor function may conflict with built-in properties
- * of Function. Esp. in ECMAScript 5 there are non-configurable and non-writable
- * built-in properties. This check issues a transpile error when a class has a static
+ * of Function. Esp. in ECMAScript 5 there are non-configurable and non-writable
+ * built-in properties. This check issues a transpile error when a class has a static
* member with the same name as a non-writable built-in property.
- *
+ *
* @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.3
* @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5
* @see http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-function-constructor
@@ -18560,16 +18588,18 @@ namespace ts {
return;
}
+ const propDeclaration = prop.valueDeclaration;
+
// index is numeric and property name is not valid numeric literal
- if (indexKind === IndexKind.Number && !isNumericName(prop.valueDeclaration.name)) {
+ if (indexKind === IndexKind.Number && !(propDeclaration ? isNumericName(propDeclaration.name) : isNumericLiteralName(prop.name))) {
return;
}
// perform property check if property or indexer is declared in 'type'
// this allows to rule out cases when both property and indexer are inherited from the base class
let errorNode: Node;
- if (prop.valueDeclaration.name.kind === SyntaxKind.ComputedPropertyName || prop.parent === containingType.symbol) {
- errorNode = prop.valueDeclaration;
+ if (propDeclaration && (propDeclaration.name.kind === SyntaxKind.ComputedPropertyName || prop.parent === containingType.symbol)) {
+ errorNode = propDeclaration;
}
else if (indexDeclaration) {
errorNode = indexDeclaration;
@@ -18682,7 +18712,11 @@ namespace ts {
const staticType = getTypeOfSymbol(symbol);
checkTypeParameterListsIdentical(node, symbol);
checkClassForDuplicateDeclarations(node);
- checkClassForStaticPropertyNameConflicts(node);
+
+ // Only check for reserved static identifiers on non-ambient context.
+ if (!isInAmbientContext(node)) {
+ checkClassForStaticPropertyNameConflicts(node);
+ }
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
if (baseTypeNode) {
@@ -18708,7 +18742,7 @@ namespace ts {
checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node,
Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
- if (baseType.symbol.valueDeclaration &&
+ if (baseType.symbol && baseType.symbol.valueDeclaration &&
!isInAmbientContext(baseType.symbol.valueDeclaration) &&
baseType.symbol.valueDeclaration.kind === SyntaxKind.ClassDeclaration) {
if (!isBlockScopedNameDeclaredBeforeUse(baseType.symbol.valueDeclaration, node)) {
@@ -18740,8 +18774,7 @@ namespace ts {
if (produceDiagnostics) {
const t = getTypeFromTypeNode(typeRefNode);
if (t !== unknownType) {
- const declaredType = getObjectFlags(t) & ObjectFlags.Reference ? (t).target : t;
- if (getObjectFlags(declaredType) & ObjectFlags.ClassOrInterface) {
+ if (isValidBaseType(t)) {
checkTypeAssignableTo(typeWithThis, getTypeWithThisArgument(t, type.thisType), node.name || node, Diagnostics.Class_0_incorrectly_implements_interface_1);
}
else {
@@ -18781,7 +18814,7 @@ namespace ts {
return forEach(symbol.declarations, d => isClassLike(d) ? d : undefined);
}
- function checkKindsOfPropertyMemberOverrides(type: InterfaceType, baseType: ObjectType): void {
+ function checkKindsOfPropertyMemberOverrides(type: InterfaceType, baseType: BaseType): void {
// TypeScript 1.0 spec (April 2014): 8.2.3
// A derived class inherits all members from its base class it doesn't override.
@@ -18798,7 +18831,7 @@ namespace ts {
// derived class instance member variables and accessors, but not by other kinds of members.
// NOTE: assignability is checked in checkClassDeclaration
- const baseProperties = getPropertiesOfObjectType(baseType);
+ const baseProperties = getPropertiesOfType(baseType);
for (const baseProperty of baseProperties) {
const base = getTargetSymbol(baseProperty);
@@ -18922,7 +18955,7 @@ namespace ts {
let ok = true;
for (const base of baseTypes) {
- const properties = getPropertiesOfObjectType(getTypeWithThisArgument(base, type.thisType));
+ const properties = getPropertiesOfType(getTypeWithThisArgument(base, type.thisType));
for (const prop of properties) {
const existing = seen.get(prop.name);
if (!existing) {
@@ -20549,6 +20582,10 @@ namespace ts {
const links = symbol as SymbolLinks;
return [links.leftSpread, links.rightSpread];
}
+ if ((symbol as SymbolLinks).mappedTypeOrigin) {
+ return getRootSymbols((symbol as SymbolLinks).mappedTypeOrigin);
+ }
+
let target: Symbol;
let next = symbol;
while (next = getSymbolLinks(next).target) {
@@ -20567,7 +20604,8 @@ namespace ts {
if (!isGeneratedIdentifier(node)) {
node = getParseTreeNode(node, isIdentifier);
if (node) {
- return getReferencedValueSymbol(node) === argumentsSymbol;
+ const isPropertyName = node.parent.kind === SyntaxKind.PropertyAccessExpression && (node.parent).name === node;
+ return !isPropertyName && getReferencedValueSymbol(node) === argumentsSymbol;
}
}
@@ -20862,18 +20900,21 @@ namespace ts {
function getTypeReferenceSerializationKind(typeName: EntityName, location?: Node): TypeReferenceSerializationKind {
// Resolve the symbol as a value to ensure the type can be reached at runtime during emit.
const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location);
- const globalPromiseSymbol = tryGetGlobalPromiseConstructorSymbol();
- if (globalPromiseSymbol && valueSymbol === globalPromiseSymbol) {
- return TypeReferenceSerializationKind.Promise;
- }
-
- const constructorType = valueSymbol ? getTypeOfSymbol(valueSymbol) : undefined;
- if (constructorType && isConstructorType(constructorType)) {
- return TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue;
- }
// Resolve the symbol as a type so that we can provide a more useful hint for the type serializer.
const typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location);
+ if (valueSymbol && valueSymbol === typeSymbol) {
+ const globalPromiseSymbol = tryGetGlobalPromiseConstructorSymbol();
+ if (globalPromiseSymbol && valueSymbol === globalPromiseSymbol) {
+ return TypeReferenceSerializationKind.Promise;
+ }
+
+ const constructorType = getTypeOfSymbol(valueSymbol);
+ if (constructorType && isConstructorType(constructorType)) {
+ return TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue;
+ }
+ }
+
// We might not be able to resolve type symbol so use unknown type in that case (eg error case)
if (!typeSymbol) {
return TypeReferenceSerializationKind.ObjectType;
diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts
index b222df53630..248726693c9 100644
--- a/src/compiler/commandLineParser.ts
+++ b/src/compiler/commandLineParser.ts
@@ -67,10 +67,11 @@ namespace ts {
name: "jsx",
type: createMapFromTemplate({
"preserve": JsxEmit.Preserve,
+ "react-native": JsxEmit.ReactNative,
"react": JsxEmit.React
}),
paramType: Diagnostics.KIND,
- description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_or_react,
+ description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_react_native_or_react,
},
{
name: "reactNamespace",
diff --git a/src/compiler/core.ts b/src/compiler/core.ts
index c26e04ee1f3..aa2faec31d7 100644
--- a/src/compiler/core.ts
+++ b/src/compiler/core.ts
@@ -204,6 +204,10 @@ namespace ts {
GreaterThan = 1
}
+ export function length(array: any[]) {
+ return array ? array.length : 0;
+ }
+
/**
* Iterates through 'array' by index and performs the callback on each element of array until the callback
* returns a truthy value, then returns that value.
diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts
index 2287de179e3..46df4fed689 100644
--- a/src/compiler/declarationEmitter.ts
+++ b/src/compiler/declarationEmitter.ts
@@ -32,7 +32,7 @@ namespace ts {
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] {
const declarationDiagnostics = createDiagnosticCollection();
- forEachExpectedEmitFile(host, getDeclarationDiagnosticsFromFile, targetSourceFile);
+ forEachEmittedFile(host, getDeclarationDiagnosticsFromFile, targetSourceFile);
return declarationDiagnostics.getDiagnostics(targetSourceFile ? targetSourceFile.fileName : undefined);
function getDeclarationDiagnosticsFromFile({ declarationFilePath }: EmitFileNames, sources: SourceFile[], isBundledEmit: boolean) {
@@ -1788,7 +1788,7 @@ namespace ts {
}
else {
// Get the declaration file path
- forEachExpectedEmitFile(host, getDeclFileName, referencedFile, emitOnlyDtsFiles);
+ forEachEmittedFile(host, getDeclFileName, referencedFile, emitOnlyDtsFiles);
}
if (declFileName) {
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index 43bb7415c88..4278784e9ab 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -2713,7 +2713,7 @@
"category": "Message",
"code": 6079
},
- "Specify JSX code generation: 'preserve' or 'react'": {
+ "Specify JSX code generation: 'preserve', 'react-native', or 'react'": {
"category": "Message",
"code": 6080
},
diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index 814d6cd76c6..4b24403bca0 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -73,7 +73,7 @@ namespace ts {
// Emit each output file
performance.mark("beforePrint");
- forEachTransformedEmitFile(host, transformed, emitFile, emitOnlyDtsFiles);
+ forEachEmittedFile(host, emitFile, transformed, emitOnlyDtsFiles);
performance.measure("printTime", "beforePrint");
// Clean up emit nodes on parse tree
@@ -88,7 +88,7 @@ namespace ts {
sourceMaps: sourceMapDataList
};
- function emitFile(jsFilePath: string, sourceMapFilePath: string, declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
+ function emitFile({ jsFilePath, sourceMapFilePath, declarationFilePath }: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) {
// Make sure not to write js file and source map file if any of them cannot be written
if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit) {
if (!emitOnlyDtsFiles) {
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index 324a21f229e..650711afc79 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -439,7 +439,7 @@ namespace ts {
function getCommonSourceDirectory() {
if (commonSourceDirectory === undefined) {
- const emittedFiles = filterSourceFilesInDirectory(files, isSourceFileFromExternalLibrary);
+ const emittedFiles = filter(files, file => sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary));
if (options.rootDir && checkSourceFilesBelongToPath(emittedFiles, options.rootDir)) {
// If a rootDir is specified and is valid use it as the commonSourceDirectory
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory);
@@ -1707,7 +1707,7 @@ namespace ts {
if (!options.noEmit && !options.suppressOutputPathCheck) {
const emitHost = getEmitHost();
const emitFilesSeen = createFileMap(!host.useCaseSensitiveFileNames() ? key => key.toLocaleLowerCase() : undefined);
- forEachExpectedEmitFile(emitHost, (emitFileNames) => {
+ forEachEmittedFile(emitHost, (emitFileNames) => {
verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen);
verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen);
});
diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts
index d0b9ef7455f..d1dab8eeb7a 100644
--- a/src/compiler/transformers/es2015.ts
+++ b/src/compiler/transformers/es2015.ts
@@ -585,7 +585,7 @@ namespace ts {
if (isGeneratedIdentifier(node)) {
return node;
}
- if (node.text !== "arguments" && !resolver.isArgumentsLocalBinding(node)) {
+ if (node.text !== "arguments" || !resolver.isArgumentsLocalBinding(node)) {
return node;
}
return convertedLoopState.argumentsName || (convertedLoopState.argumentsName = createUniqueName("arguments"));
diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts
index 6dd875965d9..c3b011fe36d 100644
--- a/src/compiler/transformers/es5.ts
+++ b/src/compiler/transformers/es5.ts
@@ -11,10 +11,10 @@ namespace ts {
export function transformES5(context: TransformationContext) {
const compilerOptions = context.getCompilerOptions();
- // enable emit notification only if using --jsx preserve
+ // enable emit notification only if using --jsx preserve or react-native
let previousOnEmitNode: (emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) => void;
let noSubstitution: boolean[];
- if (compilerOptions.jsx === JsxEmit.Preserve) {
+ if (compilerOptions.jsx === JsxEmit.Preserve || compilerOptions.jsx === JsxEmit.ReactNative) {
previousOnEmitNode = context.onEmitNode;
context.onEmitNode = onEmitNode;
context.enableEmitNotification(SyntaxKind.JsxOpeningElement);
@@ -116,4 +116,4 @@ namespace ts {
return undefined;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index f7aa3a41d53..45e6807e5c0 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -422,7 +422,7 @@
LastBinaryOperator = CaretEqualsToken,
FirstNode = QualifiedName,
FirstJSDocNode = JSDocTypeExpression,
- LastJSDocNode = JSDocLiteralType,
+ LastJSDocNode = JSDocNeverKeyword,
FirstJSDocTagNode = JSDocComment,
LastJSDocTagNode = JSDocNeverKeyword
}
@@ -2363,7 +2363,7 @@
getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo;
getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];
getIndexTypeOfType(type: Type, kind: IndexKind): Type;
- getBaseTypes(type: InterfaceType): ObjectType[];
+ getBaseTypes(type: InterfaceType): BaseType[];
getReturnTypeOfSignature(signature: Signature): Type;
/**
* Gets the type of a parameter at a given position in a signature.
@@ -2718,6 +2718,7 @@
containingType?: UnionOrIntersectionType; // Containing union or intersection type for synthetic property
leftSpread?: Symbol; // Left source for synthetic spread property
rightSpread?: Symbol; // Right source for synthetic spread property
+ mappedTypeOrigin?: Symbol; // For a property on a mapped type, points back to the orignal 'T' from 'keyof T'.
hasNonUniformType?: boolean; // True if constituents have non-uniform types
isPartial?: boolean; // True if syntheric property of union type occurs in some but not all constituents
isDiscriminantProperty?: boolean; // True if discriminant synthetic property
@@ -2918,9 +2919,12 @@
/* @internal */
resolvedBaseConstructorType?: Type; // Resolved base constructor type of class
/* @internal */
- resolvedBaseTypes: ObjectType[]; // Resolved base types
+ resolvedBaseTypes: BaseType[]; // Resolved base types
}
+ // Object type or intersection of object types
+ export type BaseType = ObjectType | IntersectionType;
+
export interface InterfaceTypeWithDeclaredMembers extends InterfaceType {
declaredProperties: Symbol[]; // Declared members
declaredCallSignatures: Signature[]; // Declared call signatures
@@ -2953,7 +2957,9 @@
export interface UnionOrIntersectionType extends Type {
types: Type[]; // Constituent types
/* @internal */
- resolvedProperties: SymbolTable; // Cache of resolved properties
+ propertyCache: SymbolTable; // Cache of resolved properties
+ /* @internal */
+ resolvedProperties: Symbol[];
/* @internal */
resolvedIndexType: IndexType;
/* @internal */
@@ -2964,7 +2970,10 @@
export interface UnionType extends UnionOrIntersectionType { }
- export interface IntersectionType extends UnionOrIntersectionType { }
+ export interface IntersectionType extends UnionOrIntersectionType {
+ /* @internal */
+ resolvedApparentType: Type;
+ }
export type StructuredType = ObjectType | UnionType | IntersectionType;
@@ -3298,7 +3307,8 @@
export const enum JsxEmit {
None = 0,
Preserve = 1,
- React = 2
+ React = 2,
+ ReactNative = 3
}
export const enum NewLineKind {
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index 5d9362df242..6172f7b2e00 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -2573,102 +2573,57 @@ namespace ts {
* @param host An EmitHost.
* @param targetSourceFile An optional target source file to emit.
*/
- export function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFile) {
+ export function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFile): SourceFile[] {
const options = host.getCompilerOptions();
+ const isSourceFileFromExternalLibrary = (file: SourceFile) => host.isSourceFileFromExternalLibrary(file);
if (options.outFile || options.out) {
const moduleKind = getEmitModuleKind(options);
const moduleEmitEnabled = moduleKind === ModuleKind.AMD || moduleKind === ModuleKind.System;
- const sourceFiles = getAllEmittableSourceFiles();
// Can emit only sources that are not declaration file and are either non module code or module with --module or --target es6 specified
- return filter(sourceFiles, moduleEmitEnabled ? isNonDeclarationFile : isBundleEmitNonExternalModule);
+ return filter(host.getSourceFiles(), sourceFile =>
+ (moduleEmitEnabled || !isExternalModule(sourceFile)) && sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary));
}
else {
- const sourceFiles = targetSourceFile === undefined ? getAllEmittableSourceFiles() : [targetSourceFile];
- return filterSourceFilesInDirectory(sourceFiles, file => host.isSourceFileFromExternalLibrary(file));
- }
-
- function getAllEmittableSourceFiles() {
- return options.noEmitForJsFiles ? filter(host.getSourceFiles(), sourceFile => !isSourceFileJavaScript(sourceFile)) : host.getSourceFiles();
+ const sourceFiles = targetSourceFile === undefined ? host.getSourceFiles() : [targetSourceFile];
+ return filter(sourceFiles, sourceFile => sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary));
}
}
- /** Don't call this for `--outFile`, just for `--outDir` or plain emit. */
- export function filterSourceFilesInDirectory(sourceFiles: SourceFile[], isSourceFileFromExternalLibrary: (file: SourceFile) => boolean): SourceFile[] {
- return filter(sourceFiles, file => shouldEmitInDirectory(file, isSourceFileFromExternalLibrary));
- }
-
- function isNonDeclarationFile(sourceFile: SourceFile) {
- return !isDeclarationFile(sourceFile);
+ /** Don't call this for `--outFile`, just for `--outDir` or plain emit. `--outFile` needs additional checks. */
+ export function sourceFileMayBeEmitted(sourceFile: SourceFile, options: CompilerOptions, isSourceFileFromExternalLibrary: (file: SourceFile) => boolean) {
+ return !(options.noEmitForJsFiles && isSourceFileJavaScript(sourceFile)) && !isDeclarationFile(sourceFile) && !isSourceFileFromExternalLibrary(sourceFile);
}
/**
- * Whether a file should be emitted in a non-`--outFile` case.
- * Don't emit if source file is a declaration file, or was located under node_modules
- */
- function shouldEmitInDirectory(sourceFile: SourceFile, isSourceFileFromExternalLibrary: (file: SourceFile) => boolean): boolean {
- return isNonDeclarationFile(sourceFile) && !isSourceFileFromExternalLibrary(sourceFile);
- }
-
- function isBundleEmitNonExternalModule(sourceFile: SourceFile) {
- return isNonDeclarationFile(sourceFile) && !isExternalModule(sourceFile);
- }
-
- /**
- * Iterates over each source file to emit. The source files are expected to have been
- * transformed for use by the pretty printer.
- *
- * Originally part of `forEachExpectedEmitFile`, this functionality was extracted to support
- * transformations.
+ * Iterates over the source files that are expected to have an emit output.
*
* @param host An EmitHost.
- * @param sourceFiles The transformed source files to emit.
* @param action The action to execute.
+ * @param sourceFilesOrTargetSourceFile
+ * If an array, the full list of source files to emit.
+ * Else, calls `getSourceFilesToEmit` with the (optional) target source file to determine the list of source files to emit.
*/
- export function forEachTransformedEmitFile(host: EmitHost, sourceFiles: SourceFile[],
- action: (jsFilePath: string, sourceMapFilePath: string, declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) => void,
+ export function forEachEmittedFile(
+ host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean) => void,
+ sourceFilesOrTargetSourceFile?: SourceFile[] | SourceFile,
emitOnlyDtsFiles?: boolean) {
+
+ const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile);
const options = host.getCompilerOptions();
- // Emit on each source file
if (options.outFile || options.out) {
- onBundledEmit(sourceFiles);
- }
- else {
- for (const sourceFile of sourceFiles) {
- // Don't emit if source file is a declaration file, or was located under node_modules
- if (!isDeclarationFile(sourceFile) && !host.isSourceFileFromExternalLibrary(sourceFile)) {
- onSingleFileEmit(host, sourceFile);
- }
- }
- }
-
- function onSingleFileEmit(host: EmitHost, sourceFile: SourceFile) {
- // JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also.
- // So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve.
- // For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve
- let extension = ".js";
- if (options.jsx === JsxEmit.Preserve) {
- if (isSourceFileJavaScript(sourceFile)) {
- if (fileExtensionIs(sourceFile.fileName, ".jsx")) {
- extension = ".jsx";
- }
- }
- else if (sourceFile.languageVariant === LanguageVariant.JSX) {
- // TypeScript source file preserving JSX syntax
- extension = ".jsx";
- }
- }
- const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, extension);
- const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
- const declarationFilePath = !isSourceFileJavaScript(sourceFile) && (options.declaration || emitOnlyDtsFiles) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined;
- action(jsFilePath, sourceMapFilePath, declarationFilePath, [sourceFile], /*isBundledEmit*/ false);
- }
-
- function onBundledEmit(sourceFiles: SourceFile[]) {
if (sourceFiles.length) {
const jsFilePath = options.outFile || options.out;
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined;
- action(jsFilePath, sourceMapFilePath, declarationFilePath, sourceFiles, /*isBundledEmit*/ true);
+ action({ jsFilePath, sourceMapFilePath, declarationFilePath }, sourceFiles, /*isBundledEmit*/true, emitOnlyDtsFiles);
+ }
+ }
+ else {
+ for (const sourceFile of sourceFiles) {
+ const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, getOutputExtension(sourceFile, options));
+ const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
+ const declarationFilePath = !isSourceFileJavaScript(sourceFile) && (emitOnlyDtsFiles || options.declaration) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined;
+ action({ jsFilePath, sourceMapFilePath, declarationFilePath }, [sourceFile], /*isBundledEmit*/false, emitOnlyDtsFiles);
}
}
}
@@ -2677,77 +2632,22 @@ namespace ts {
return options.sourceMap ? jsFilePath + ".map" : undefined;
}
- /**
- * Iterates over the source files that are expected to have an emit output. This function
- * is used by the legacy emitter and the declaration emitter and should not be used by
- * the tree transforming emitter.
- *
- * @param host An EmitHost.
- * @param action The action to execute.
- * @param targetSourceFile An optional target source file to emit.
- */
- export function forEachExpectedEmitFile(host: EmitHost,
- action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean) => void,
- targetSourceFile?: SourceFile,
- emitOnlyDtsFiles?: boolean) {
- const options = host.getCompilerOptions();
- // Emit on each source file
- if (options.outFile || options.out) {
- onBundledEmit(host);
- }
- else {
- const sourceFiles = targetSourceFile === undefined ? getSourceFilesToEmit(host) : [targetSourceFile];
- for (const sourceFile of sourceFiles) {
- if (shouldEmitInDirectory(sourceFile, file => host.isSourceFileFromExternalLibrary(file))) {
- onSingleFileEmit(host, sourceFile);
+ // JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also.
+ // So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve.
+ // For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve
+ function getOutputExtension(sourceFile: SourceFile, options: CompilerOptions): string {
+ if (options.jsx === JsxEmit.Preserve) {
+ if (isSourceFileJavaScript(sourceFile)) {
+ if (fileExtensionIs(sourceFile.fileName, ".jsx")) {
+ return ".jsx";
}
}
- }
-
- function onSingleFileEmit(host: EmitHost, sourceFile: SourceFile) {
- // JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also.
- // So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve.
- // For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve
- let extension = ".js";
- if (options.jsx === JsxEmit.Preserve) {
- if (isSourceFileJavaScript(sourceFile)) {
- if (fileExtensionIs(sourceFile.fileName, ".jsx")) {
- extension = ".jsx";
- }
- }
- else if (sourceFile.languageVariant === LanguageVariant.JSX) {
- // TypeScript source file preserving JSX syntax
- extension = ".jsx";
- }
- }
- const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, extension);
- const declarationFilePath = !isSourceFileJavaScript(sourceFile) && (emitOnlyDtsFiles || options.declaration) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined;
- const emitFileNames: EmitFileNames = {
- jsFilePath,
- sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
- declarationFilePath
- };
- action(emitFileNames, [sourceFile], /*isBundledEmit*/false, emitOnlyDtsFiles);
- }
-
- function onBundledEmit(host: EmitHost) {
- // Can emit only sources that are not declaration file and are either non module code or module with
- // --module or --target es6 specified. Files included by searching under node_modules are also not emitted.
- const bundledSources = filter(getSourceFilesToEmit(host),
- sourceFile => !isDeclarationFile(sourceFile) &&
- !host.isSourceFileFromExternalLibrary(sourceFile) &&
- (!isExternalModule(sourceFile) ||
- !!getEmitModuleKind(options)));
- if (bundledSources.length) {
- const jsFilePath = options.outFile || options.out;
- const emitFileNames: EmitFileNames = {
- jsFilePath,
- sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
- declarationFilePath: options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined
- };
- action(emitFileNames, bundledSources, /*isBundledEmit*/true, emitOnlyDtsFiles);
+ else if (sourceFile.languageVariant === LanguageVariant.JSX) {
+ // TypeScript source file preserving JSX syntax
+ return ".jsx";
}
}
+ return ".js";
}
export function getSourceFilePathInNewDir(sourceFile: SourceFile, host: EmitHost, newDirPath: string) {
diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts
index 1afb6de2cf2..721647df0cd 100644
--- a/src/harness/fourslash.ts
+++ b/src/harness/fourslash.ts
@@ -372,8 +372,8 @@ namespace FourSlash {
}
// Entry points from fourslash.ts
- public goToMarker(name = "") {
- const marker = this.getMarkerByName(name);
+ public goToMarker(name: string | Marker = "") {
+ const marker = typeof name === "string" ? this.getMarkerByName(name) : name;
if (this.activeFile.fileName !== marker.fileName) {
this.openFile(marker.fileName);
}
@@ -382,10 +382,37 @@ namespace FourSlash {
if (marker.position === -1 || marker.position > content.length) {
throw new Error(`Marker "${name}" has been invalidated by unrecoverable edits to the file.`);
}
- this.lastKnownMarker = name;
+ const mName = typeof name === "string" ? name : this.markerName(marker);
+ this.lastKnownMarker = mName;
this.goToPosition(marker.position);
}
+ public goToEachMarker(action: () => void) {
+ const markers = this.getMarkers();
+ assert(markers.length);
+ for (const marker of markers) {
+ this.goToMarker(marker);
+ action();
+ }
+ }
+
+ public goToEachRange(action: () => void) {
+ const ranges = this.getRanges();
+ assert(ranges.length);
+ for (const range of ranges) {
+ this.goToRangeStart(range);
+ action();
+ }
+ }
+
+ private markerName(m: Marker): string {
+ return ts.forEachEntry(this.testData.markerPositions, (marker, name) => {
+ if (marker === m) {
+ return name;
+ }
+ })!;
+ }
+
public goToPosition(pos: number) {
this.currentCaretPosition = pos;
}
@@ -1668,7 +1695,7 @@ namespace FourSlash {
this.goToPosition(len);
}
- private goToRangeStart({fileName, start}: Range) {
+ public goToRangeStart({fileName, start}: Range) {
this.openFile(fileName);
this.goToPosition(start);
}
@@ -2365,6 +2392,21 @@ namespace FourSlash {
return this.languageService.getDocumentHighlights(this.activeFile.fileName, this.currentCaretPosition, filesToSearch);
}
+ public verifyRangesAreOccurrences(isWriteAccess?: boolean) {
+ const ranges = this.getRanges();
+ for (const r of ranges) {
+ this.goToRangeStart(r);
+ this.verifyOccurrencesAtPositionListCount(ranges.length);
+ for (const range of ranges) {
+ this.verifyOccurrencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess);
+ }
+ }
+ }
+
+ public verifyRangesAreRenameLocations(findInStrings: boolean, findInComments: boolean) {
+ this.goToEachRange(() => this.verifyRenameLocations(findInStrings, findInComments));
+ }
+
public verifyRangesWithSameTextAreDocumentHighlights() {
this.rangesByText().forEach(ranges => this.verifyRangesAreDocumentHighlights(ranges));
}
@@ -3078,10 +3120,22 @@ namespace FourSlashInterface {
// Moves the caret to the specified marker,
// or the anonymous marker ('/**/') if no name
// is given
- public marker(name?: string) {
+ public marker(name?: string | FourSlash.Marker) {
this.state.goToMarker(name);
}
+ public eachMarker(action: () => void) {
+ this.state.goToEachMarker(action);
+ }
+
+ public rangeStart(range: FourSlash.Range) {
+ this.state.goToRangeStart(range);
+ }
+
+ public eachRange(action: () => void) {
+ this.state.goToEachRange(action);
+ }
+
public bof() {
this.state.goToBOF();
}
@@ -3432,6 +3486,14 @@ namespace FourSlashInterface {
this.state.verifyOccurrencesAtPositionListCount(expectedCount);
}
+ public rangesAreOccurrences(isWriteAccess?: boolean) {
+ this.state.verifyRangesAreOccurrences(isWriteAccess);
+ }
+
+ public rangesAreRenameLocations(findInStrings = false, findInComments = false) {
+ this.state.verifyRangesAreRenameLocations(findInStrings, findInComments);
+ }
+
public rangesAreDocumentHighlights(ranges?: FourSlash.Range[]) {
this.state.verifyRangesAreDocumentHighlights(ranges);
}
diff --git a/src/harness/unittests/commandLineParsing.ts b/src/harness/unittests/commandLineParsing.ts
index 8c691992043..1895fe2d60e 100644
--- a/src/harness/unittests/commandLineParsing.ts
+++ b/src/harness/unittests/commandLineParsing.ts
@@ -87,7 +87,7 @@ namespace ts {
start: undefined,
length: undefined,
}, {
- messageText: "Argument for '--jsx' option must be: 'preserve', 'react'",
+ messageText: "Argument for '--jsx' option must be: 'preserve', 'react-native', 'react'",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
diff --git a/src/harness/unittests/convertCompilerOptionsFromJson.ts b/src/harness/unittests/convertCompilerOptionsFromJson.ts
index f44dc259710..4e442173883 100644
--- a/src/harness/unittests/convertCompilerOptionsFromJson.ts
+++ b/src/harness/unittests/convertCompilerOptionsFromJson.ts
@@ -94,7 +94,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
- messageText: "Argument for '--jsx' option must be: 'preserve', 'react'",
+ messageText: "Argument for '--jsx' option must be: 'preserve', 'react-native', 'react'",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
diff --git a/src/harness/unittests/jsDocParsing.ts b/src/harness/unittests/jsDocParsing.ts
index addd01b0e0a..98c32c77778 100644
--- a/src/harness/unittests/jsDocParsing.ts
+++ b/src/harness/unittests/jsDocParsing.ts
@@ -288,5 +288,24 @@ namespace ts {
*/`);
});
});
+ describe("getFirstToken", () => {
+ it("gets jsdoc", () => {
+ const root = ts.createSourceFile("foo.ts", "/** comment */var a = true;", ts.ScriptTarget.ES5, /*setParentNodes*/ true);
+ assert.isDefined(root);
+ assert.equal(root.kind, ts.SyntaxKind.SourceFile);
+ const first = root.getFirstToken();
+ assert.isDefined(first);
+ assert.equal(first.kind, ts.SyntaxKind.VarKeyword);
+ });
+ });
+ describe("getLastToken", () => {
+ it("gets jsdoc", () => {
+ const root = ts.createSourceFile("foo.ts", "var a = true;/** comment */", ts.ScriptTarget.ES5, /*setParentNodes*/ true);
+ assert.isDefined(root);
+ const last = root.getLastToken();
+ assert.isDefined(last);
+ assert.equal(last.kind, ts.SyntaxKind.EndOfFileToken);
+ });
+ });
});
}
diff --git a/src/harness/unittests/matchFiles.ts b/src/harness/unittests/matchFiles.ts
index c562fcefe91..38e5c6c4393 100644
--- a/src/harness/unittests/matchFiles.ts
+++ b/src/harness/unittests/matchFiles.ts
@@ -909,6 +909,31 @@ namespace ts {
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
assertParsed(actual, expected);
});
+ it("with jsx=react-native, allowJs=false", () => {
+ const json = {
+ compilerOptions: {
+ jsx: "react-native",
+ allowJs: false
+ }
+ };
+ const expected: ts.ParsedCommandLine = {
+ options: {
+ jsx: ts.JsxEmit.ReactNative,
+ allowJs: false
+ },
+ errors: [],
+ fileNames: [
+ "c:/dev/a.ts",
+ "c:/dev/b.tsx",
+ "c:/dev/c.tsx",
+ ],
+ wildcardDirectories: {
+ "c:/dev": ts.WatchDirectoryFlags.Recursive
+ }
+ };
+ const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
+ assertParsed(actual, expected);
+ });
it("with jsx=none, allowJs=true", () => {
const json = {
compilerOptions: {
@@ -961,6 +986,33 @@ namespace ts {
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
assertParsed(actual, expected);
});
+ it("with jsx=react-native, allowJs=true", () => {
+ const json = {
+ compilerOptions: {
+ jsx: "react-native",
+ allowJs: true
+ }
+ };
+ const expected: ts.ParsedCommandLine = {
+ options: {
+ jsx: ts.JsxEmit.ReactNative,
+ allowJs: true
+ },
+ errors: [],
+ fileNames: [
+ "c:/dev/a.ts",
+ "c:/dev/b.tsx",
+ "c:/dev/c.tsx",
+ "c:/dev/d.js",
+ "c:/dev/e.jsx",
+ ],
+ wildcardDirectories: {
+ "c:/dev": ts.WatchDirectoryFlags.Recursive
+ }
+ };
+ const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
+ assertParsed(actual, expected);
+ });
it("exclude .min.js files using wildcards", () => {
const json = {
compilerOptions: {
@@ -1306,4 +1358,4 @@ namespace ts {
});
});
});
-}
\ No newline at end of file
+}
diff --git a/src/lib/es2015.collection.d.ts b/src/lib/es2015.collection.d.ts
index 6a2c43cd050..75a11b5eb17 100644
--- a/src/lib/es2015.collection.d.ts
+++ b/src/lib/es2015.collection.d.ts
@@ -4,7 +4,7 @@ interface Map {
forEach(callbackfn: (value: V, key: K, map: Map) => void, thisArg?: any): void;
get(key: K): V | undefined;
has(key: K): boolean;
- set(key: K, value?: V): this;
+ set(key: K, value: V): this;
readonly size: number;
}
@@ -26,7 +26,7 @@ interface WeakMap {
delete(key: K): boolean;
get(key: K): V | undefined;
has(key: K): boolean;
- set(key: K, value?: V): this;
+ set(key: K, value: V): this;
}
interface WeakMapConstructor {
diff --git a/src/lib/es2015.symbol.d.ts b/src/lib/es2015.symbol.d.ts
index cd7e45595f0..d7ea4fa0328 100644
--- a/src/lib/es2015.symbol.d.ts
+++ b/src/lib/es2015.symbol.d.ts
@@ -3,7 +3,7 @@ interface Symbol {
toString(): string;
/** Returns the primitive value of the specified object. */
- valueOf(): Object;
+ valueOf(): symbol;
}
interface SymbolConstructor {
diff --git a/src/server/protocol.ts b/src/server/protocol.ts
index 680b81dff99..e3fe17362d7 100644
--- a/src/server/protocol.ts
+++ b/src/server/protocol.ts
@@ -417,7 +417,7 @@ namespace ts.server.protocol {
startOffset: number;
/**
- * Position (can be specified instead of line/offset pair)
+ * Position (can be specified instead of line/offset pair)
*/
/* @internal */
startPosition?: number;
@@ -433,7 +433,7 @@ namespace ts.server.protocol {
endOffset: number;
/**
- * Position (can be specified instead of line/offset pair)
+ * Position (can be specified instead of line/offset pair)
*/
/* @internal */
endPosition?: number;
@@ -445,7 +445,7 @@ namespace ts.server.protocol {
}
/**
- * Response for GetCodeFixes request.
+ * Response for GetCodeFixes request.
*/
export interface GetCodeFixesResponse extends Response {
body?: CodeAction[];
@@ -2272,10 +2272,11 @@ namespace ts.server.protocol {
export namespace JsxEmit {
export type None = "None";
export type Preserve = "Preserve";
+ export type ReactNative = "ReactNative";
export type React = "React";
}
- export type JsxEmit = JsxEmit.None | JsxEmit.Preserve | JsxEmit.React;
+ export type JsxEmit = JsxEmit.None | JsxEmit.Preserve | JsxEmit.React | JsxEmit.ReactNative;
export namespace ModuleKind {
export type None = "None";
diff --git a/src/services/completions.ts b/src/services/completions.ts
index 45e9da9fd06..41ba2b264b4 100644
--- a/src/services/completions.ts
+++ b/src/services/completions.ts
@@ -1,6 +1,6 @@
/* @internal */
namespace ts.Completions {
- type Log = (message: string) => void;
+ export type Log = (message: string) => void;
export function getCompletionsAtPosition(host: LanguageServiceHost, typeChecker: TypeChecker, log: Log, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number): CompletionInfo | undefined {
if (isInReferenceComment(sourceFile, position)) {
diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts
index 79fa0236bc5..778a007ded5 100644
--- a/src/services/documentHighlights.ts
+++ b/src/services/documentHighlights.ts
@@ -17,25 +17,11 @@ namespace ts.DocumentHighlights {
}
function getSemanticDocumentHighlights(node: Node, typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] {
- if (node.kind === SyntaxKind.Identifier ||
- node.kind === SyntaxKind.ThisKeyword ||
- node.kind === SyntaxKind.ThisType ||
- node.kind === SyntaxKind.SuperKeyword ||
- node.kind === SyntaxKind.StringLiteral ||
- isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) {
-
- const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFilesToSearch, /*findInStrings*/ false, /*findInComments*/ false, /*implementations*/false);
- return convertReferencedSymbols(referencedSymbols);
- }
-
- return undefined;
+ const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFilesToSearch, /*findInStrings*/false, /*findInComments*/false, /*implementations*/false);
+ return referencedSymbols && convertReferencedSymbols(referencedSymbols);
}
function convertReferencedSymbols(referencedSymbols: ReferencedSymbol[]): DocumentHighlights[] {
- if (!referencedSymbols) {
- return undefined;
- }
-
const fileNameToDocumentHighlights = createMap();
const result: DocumentHighlights[] = [];
for (const referencedSymbol of referencedSymbols) {
diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts
index 68960c7a887..5c1f607bd62 100644
--- a/src/services/findAllReferences.ts
+++ b/src/services/findAllReferences.ts
@@ -1,29 +1,16 @@
/* @internal */
namespace ts.FindAllReferences {
- export function findReferencedSymbols(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] {
+ export function findReferencedSymbols(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] | undefined {
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
- if (node === sourceFile) {
- return undefined;
- }
-
- switch (node.kind) {
- case SyntaxKind.NumericLiteral:
- if (!isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) {
- break;
- }
- // Fallthrough
- case SyntaxKind.Identifier:
- case SyntaxKind.ThisKeyword:
- // case SyntaxKind.SuperKeyword: TODO:GH#9268
- case SyntaxKind.ConstructorKeyword:
- case SyntaxKind.StringLiteral:
- return getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments, /*implementations*/false);
- }
- return undefined;
+ return getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments, /*implementations*/false);
}
- export function getReferencedSymbolsForNode(typeChecker: TypeChecker, cancellationToken: CancellationToken, node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean, implementations: boolean): ReferencedSymbol[] {
+ export function getReferencedSymbolsForNode(typeChecker: TypeChecker, cancellationToken: CancellationToken, node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean, implementations: boolean): ReferencedSymbol[] | undefined {
if (!implementations) {
+ if (isTypeKeyword(node.kind)) {
+ return getAllReferencesForKeyword(sourceFiles, node.kind, cancellationToken);
+ }
+
// Labels
if (isLabelName(node)) {
if (isJumpStatementTarget(node)) {
@@ -68,8 +55,6 @@ namespace ts.FindAllReferences {
return undefined;
}
- let result: ReferencedSymbol[];
-
// Compute the meaning from the location and the symbol it references
const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations);
@@ -84,6 +69,7 @@ namespace ts.FindAllReferences {
// Maps from a symbol ID to the ReferencedSymbol entry in 'result'.
const symbolToIndex: number[] = [];
+ let result: ReferencedSymbol[];
if (scope) {
result = [];
getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex, implementations, typeChecker, cancellationToken);
@@ -92,10 +78,7 @@ namespace ts.FindAllReferences {
const internedName = getInternedName(symbol, node);
for (const sourceFile of sourceFiles) {
cancellationToken.throwIfCancellationRequested();
-
- const nameTable = getNameTable(sourceFile);
-
- if (nameTable.get(internedName) !== undefined) {
+ if (sourceFileHasName(sourceFile, internedName)) {
result = result || [];
getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex, implementations, typeChecker, cancellationToken);
}
@@ -105,9 +88,13 @@ namespace ts.FindAllReferences {
return result;
}
+ function sourceFileHasName(sourceFile: SourceFile, name: string): boolean {
+ return getNameTable(sourceFile).get(name) !== undefined;
+ }
+
function getDefinition(symbol: Symbol, node: Node, typeChecker: TypeChecker): ReferencedSymbolDefinitionInfo {
- const info = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, node.getSourceFile(), getContainerNode(node), node);
- const name = map(info.displayParts, p => p.text).join("");
+ const { displayParts, symbolKind } = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, node.getSourceFile(), getContainerNode(node), node);
+ const name = displayParts.map(p => p.text).join("");
const declarations = symbol.declarations;
if (!declarations || declarations.length === 0) {
return undefined;
@@ -117,10 +104,10 @@ namespace ts.FindAllReferences {
containerKind: "",
containerName: "",
name,
- kind: info.symbolKind,
+ kind: symbolKind,
fileName: declarations[0].getSourceFile().fileName,
textSpan: createTextSpan(declarations[0].getStart(), 0),
- displayParts: info.displayParts
+ displayParts
};
}
@@ -351,6 +338,43 @@ namespace ts.FindAllReferences {
}
}
+ function getAllReferencesForKeyword(sourceFiles: SourceFile[], keywordKind: ts.SyntaxKind, cancellationToken: CancellationToken): ReferencedSymbol[] {
+ const name = tokenToString(keywordKind);
+ const definition: ReferencedSymbolDefinitionInfo = {
+ containerKind: "",
+ containerName: "",
+ fileName: "",
+ kind: ScriptElementKind.keyword,
+ name,
+ textSpan: createTextSpan(0, 1),
+ displayParts: [{ text: name, kind: ScriptElementKind.keyword }]
+ }
+
+ const references: ReferenceEntry[] = [];
+ for (const sourceFile of sourceFiles) {
+ cancellationToken.throwIfCancellationRequested();
+ addReferencesForKeywordInFile(sourceFile, keywordKind, name, cancellationToken, references);
+ }
+
+ return [{ definition, references }];
+ }
+
+ function addReferencesForKeywordInFile(sourceFile: SourceFile, kind: SyntaxKind, searchText: string, cancellationToken: CancellationToken, references: Push): void {
+ const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, sourceFile.getStart(), sourceFile.getEnd(), cancellationToken);
+ for (const position of possiblePositions) {
+ cancellationToken.throwIfCancellationRequested();
+ const referenceLocation = getTouchingPropertyName(sourceFile, position);
+ if (referenceLocation.kind === kind) {
+ references.push({
+ textSpan: createTextSpanFromNode(referenceLocation),
+ fileName: sourceFile.fileName,
+ isWriteAccess: false,
+ isDefinition: false,
+ });
+ }
+ }
+ }
+
/** Search within node "container" for references for a search value, where the search value is defined as a
* tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
* searchLocation: a node where the search value
@@ -375,67 +399,64 @@ namespace ts.FindAllReferences {
const parents = getParentSymbolsOfPropertyAccess();
const inheritsFromCache: Map = createMap();
+ // Build the set of symbols to search for, initially it has only the current symbol
+ const searchSymbols = populateSearchSymbolSet(searchSymbol, searchLocation, typeChecker, implementations);
- if (possiblePositions.length) {
- // Build the set of symbols to search for, initially it has only the current symbol
- const searchSymbols = populateSearchSymbolSet(searchSymbol, searchLocation, typeChecker, implementations);
+ for (const position of possiblePositions) {
+ cancellationToken.throwIfCancellationRequested();
- forEach(possiblePositions, position => {
- cancellationToken.throwIfCancellationRequested();
+ const referenceLocation = getTouchingPropertyName(sourceFile, position);
+ if (!isValidReferencePosition(referenceLocation, searchText)) {
+ // This wasn't the start of a token. Check to see if it might be a
+ // match in a comment or string if that's what the caller is asking
+ // for.
+ if (!implementations && ((findInStrings && isInString(sourceFile, position)) ||
+ (findInComments && isInNonReferenceComment(sourceFile, position)))) {
- const referenceLocation = getTouchingPropertyName(sourceFile, position);
- if (!isValidReferencePosition(referenceLocation, searchText)) {
- // This wasn't the start of a token. Check to see if it might be a
- // match in a comment or string if that's what the caller is asking
- // for.
- if (!implementations && ((findInStrings && isInString(sourceFile, position)) ||
- (findInComments && isInNonReferenceComment(sourceFile, position)))) {
-
- // In the case where we're looking inside comments/strings, we don't have
- // an actual definition. So just use 'undefined' here. Features like
- // 'Rename' won't care (as they ignore the definitions), and features like
- // 'FindReferences' will just filter out these results.
- result.push({
- definition: undefined,
- references: [{
- fileName: sourceFile.fileName,
- textSpan: createTextSpan(position, searchText.length),
- isWriteAccess: false,
- isDefinition: false
- }]
- });
- }
- return;
+ // In the case where we're looking inside comments/strings, we don't have
+ // an actual definition. So just use 'undefined' here. Features like
+ // 'Rename' won't care (as they ignore the definitions), and features like
+ // 'FindReferences' will just filter out these results.
+ result.push({
+ definition: undefined,
+ references: [{
+ fileName: sourceFile.fileName,
+ textSpan: createTextSpan(position, searchText.length),
+ isWriteAccess: false,
+ isDefinition: false
+ }]
+ });
}
+ continue;
+ }
- if (!(getMeaningFromLocation(referenceLocation) & searchMeaning)) {
- return;
+ if (!(getMeaningFromLocation(referenceLocation) & searchMeaning)) {
+ continue;
+ }
+
+ const referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation);
+ if (referenceSymbol) {
+ const referenceSymbolDeclaration = referenceSymbol.valueDeclaration;
+ const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration);
+ const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation,
+ /*searchLocationIsConstructor*/ searchLocation.kind === SyntaxKind.ConstructorKeyword, parents, inheritsFromCache, typeChecker);
+
+ if (relatedSymbol) {
+ addReferenceToRelatedSymbol(referenceLocation, relatedSymbol);
}
-
- const referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation);
- if (referenceSymbol) {
- const referenceSymbolDeclaration = referenceSymbol.valueDeclaration;
- const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration);
- const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation,
- /*searchLocationIsConstructor*/ searchLocation.kind === SyntaxKind.ConstructorKeyword, parents, inheritsFromCache, typeChecker);
-
- if (relatedSymbol) {
- addReferenceToRelatedSymbol(referenceLocation, relatedSymbol);
- }
- /* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
- * has two meaning : property name and property value. Therefore when we do findAllReference at the position where
- * an identifier is declared, the language service should return the position of the variable declaration as well as
- * the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the
- * position of property accessing, the referenceEntry of such position will be handled in the first case.
- */
- else if (!(referenceSymbol.flags & SymbolFlags.Transient) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) {
- addReferenceToRelatedSymbol(referenceSymbolDeclaration.name, shorthandValueSymbol);
- }
- else if (searchLocation.kind === SyntaxKind.ConstructorKeyword) {
- findAdditionalConstructorReferences(referenceSymbol, referenceLocation);
- }
+ /* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
+ * has two meaning : property name and property value. Therefore when we do findAllReference at the position where
+ * an identifier is declared, the language service should return the position of the variable declaration as well as
+ * the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the
+ * position of property accessing, the referenceEntry of such position will be handled in the first case.
+ */
+ else if (!(referenceSymbol.flags & SymbolFlags.Transient) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) {
+ addReferenceToRelatedSymbol(referenceSymbolDeclaration.name, shorthandValueSymbol);
}
- });
+ else if (searchLocation.kind === SyntaxKind.ConstructorKeyword) {
+ findAdditionalConstructorReferences(referenceSymbol, referenceLocation);
+ }
+ }
}
return;
diff --git a/src/services/services.ts b/src/services/services.ts
index 62673c01c97..25c17bd67c3 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -193,9 +193,10 @@ namespace ts {
return undefined;
}
- const child = children[0];
-
- return child.kind < SyntaxKind.FirstNode ? child : child.getFirstToken(sourceFile);
+ const child = ts.find(children, kid => kid.kind < SyntaxKind.FirstJSDocNode || kid.kind > SyntaxKind.LastJSDocNode);
+ return child.kind < SyntaxKind.FirstNode ?
+ child :
+ child.getFirstToken(sourceFile);
}
public getLastToken(sourceFile?: SourceFile): Node {
@@ -379,7 +380,7 @@ namespace ts {
getNumberIndexType(): Type {
return this.checker.getIndexTypeOfType(this, IndexKind.Number);
}
- getBaseTypes(): ObjectType[] {
+ getBaseTypes(): BaseType[] {
return this.flags & TypeFlags.Object && this.objectFlags & (ObjectFlags.Class | ObjectFlags.Interface)
? this.checker.getBaseTypes(this)
: undefined;
@@ -1959,11 +1960,9 @@ namespace ts {
function walk(node: Node) {
switch (node.kind) {
- case SyntaxKind.Identifier: {
- const text = (node).text;
- nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1);
+ case SyntaxKind.Identifier:
+ setNameTable((node).text, node);
break;
- }
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
// We want to store any numbers/strings if they were a name that could be
@@ -1974,9 +1973,7 @@ namespace ts {
node.parent.kind === SyntaxKind.ExternalModuleReference ||
isArgumentOfElementAccessExpression(node) ||
isLiteralComputedPropertyDeclarationName(node)) {
-
- const text = (node).text;
- nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1);
+ setNameTable((node).text, node);
}
break;
default:
@@ -1988,6 +1985,10 @@ namespace ts {
}
}
}
+
+ function setNameTable(text: string, node: ts.Node): void {
+ nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1);
+ }
}
function isObjectLiteralElement(node: Node): node is ObjectLiteralElement {
diff --git a/src/services/types.ts b/src/services/types.ts
index 3a195c82f42..a6ca3852597 100644
--- a/src/services/types.ts
+++ b/src/services/types.ts
@@ -33,7 +33,7 @@ namespace ts {
getConstructSignatures(): Signature[];
getStringIndexType(): Type;
getNumberIndexType(): Type;
- getBaseTypes(): ObjectType[];
+ getBaseTypes(): BaseType[];
getNonNullableType(): Type;
}
@@ -495,7 +495,7 @@ namespace ts {
export interface SymbolDisplayPart {
text: string;
- kind: string;
+ kind: string; // A ScriptElementKind
}
export interface QuickInfo {
diff --git a/src/services/utilities.ts b/src/services/utilities.ts
index eeb9725ba47..8240d05d016 100644
--- a/src/services/utilities.ts
+++ b/src/services/utilities.ts
@@ -1,4 +1,4 @@
-// These utilities are common to multiple language service features.
+// These utilities are common to multiple language service features.
/* @internal */
namespace ts {
export const scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true);
@@ -72,7 +72,10 @@ namespace ts {
}
export function getMeaningFromLocation(node: Node): SemanticMeaning {
- if (node.parent.kind === SyntaxKind.ExportAssignment) {
+ if (node.kind === SyntaxKind.SourceFile) {
+ return SemanticMeaning.Value;
+ }
+ else if (node.parent.kind === SyntaxKind.ExportAssignment) {
return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace;
}
else if (isInRightSideOfImport(node)) {
@@ -1117,6 +1120,22 @@ namespace ts {
export function createTextSpanFromNode(node: Node, sourceFile?: SourceFile): TextSpan {
return createTextSpanFromBounds(node.getStart(sourceFile), node.getEnd());
}
+
+ export function isTypeKeyword(kind: SyntaxKind): boolean {
+ switch (kind) {
+ case SyntaxKind.AnyKeyword:
+ case SyntaxKind.BooleanKeyword:
+ case SyntaxKind.NeverKeyword:
+ case SyntaxKind.NumberKeyword:
+ case SyntaxKind.ObjectKeyword:
+ case SyntaxKind.StringKeyword:
+ case SyntaxKind.SymbolKeyword:
+ case SyntaxKind.VoidKeyword:
+ return true;
+ default:
+ return false;
+ }
+ }
}
// Display-part writer helpers
diff --git a/tests/baselines/reference/argumentsAsPropertyName.js b/tests/baselines/reference/argumentsAsPropertyName.js
new file mode 100644
index 00000000000..a4197c0a1d2
--- /dev/null
+++ b/tests/baselines/reference/argumentsAsPropertyName.js
@@ -0,0 +1,29 @@
+//// [argumentsAsPropertyName.ts]
+// target: es5
+type MyType = {
+ arguments: Array
+}
+
+declare function use(s: any);
+
+function myFunction(myType: MyType) {
+ for (let i = 0; i < 10; i++) {
+ use(myType.arguments[i]);
+ // create closure so that tsc will turn loop body into function
+ const x = 5;
+ [1, 2, 3].forEach(function(j) { use(x); })
+ }
+}
+
+//// [argumentsAsPropertyName.js]
+function myFunction(myType) {
+ var _loop_1 = function (i) {
+ use(myType.arguments[i]);
+ // create closure so that tsc will turn loop body into function
+ var x = 5;
+ [1, 2, 3].forEach(function (j) { use(x); });
+ };
+ for (var i = 0; i < 10; i++) {
+ _loop_1(i);
+ }
+}
diff --git a/tests/baselines/reference/argumentsAsPropertyName.symbols b/tests/baselines/reference/argumentsAsPropertyName.symbols
new file mode 100644
index 00000000000..1e3e41abb6e
--- /dev/null
+++ b/tests/baselines/reference/argumentsAsPropertyName.symbols
@@ -0,0 +1,43 @@
+=== tests/cases/compiler/argumentsAsPropertyName.ts ===
+// target: es5
+type MyType = {
+>MyType : Symbol(MyType, Decl(argumentsAsPropertyName.ts, 0, 0))
+
+ arguments: Array
+>arguments : Symbol(arguments, Decl(argumentsAsPropertyName.ts, 1, 15))
+>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
+}
+
+declare function use(s: any);
+>use : Symbol(use, Decl(argumentsAsPropertyName.ts, 3, 1))
+>s : Symbol(s, Decl(argumentsAsPropertyName.ts, 5, 21))
+
+function myFunction(myType: MyType) {
+>myFunction : Symbol(myFunction, Decl(argumentsAsPropertyName.ts, 5, 29))
+>myType : Symbol(myType, Decl(argumentsAsPropertyName.ts, 7, 20))
+>MyType : Symbol(MyType, Decl(argumentsAsPropertyName.ts, 0, 0))
+
+ for (let i = 0; i < 10; i++) {
+>i : Symbol(i, Decl(argumentsAsPropertyName.ts, 8, 12))
+>i : Symbol(i, Decl(argumentsAsPropertyName.ts, 8, 12))
+>i : Symbol(i, Decl(argumentsAsPropertyName.ts, 8, 12))
+
+ use(myType.arguments[i]);
+>use : Symbol(use, Decl(argumentsAsPropertyName.ts, 3, 1))
+>myType.arguments : Symbol(arguments, Decl(argumentsAsPropertyName.ts, 1, 15))
+>myType : Symbol(myType, Decl(argumentsAsPropertyName.ts, 7, 20))
+>arguments : Symbol(arguments, Decl(argumentsAsPropertyName.ts, 1, 15))
+>i : Symbol(i, Decl(argumentsAsPropertyName.ts, 8, 12))
+
+ // create closure so that tsc will turn loop body into function
+ const x = 5;
+>x : Symbol(x, Decl(argumentsAsPropertyName.ts, 11, 13))
+
+ [1, 2, 3].forEach(function(j) { use(x); })
+>[1, 2, 3].forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --))
+>forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --))
+>j : Symbol(j, Decl(argumentsAsPropertyName.ts, 12, 35))
+>use : Symbol(use, Decl(argumentsAsPropertyName.ts, 3, 1))
+>x : Symbol(x, Decl(argumentsAsPropertyName.ts, 11, 13))
+ }
+}
diff --git a/tests/baselines/reference/argumentsAsPropertyName.types b/tests/baselines/reference/argumentsAsPropertyName.types
new file mode 100644
index 00000000000..d0aaaa1cc72
--- /dev/null
+++ b/tests/baselines/reference/argumentsAsPropertyName.types
@@ -0,0 +1,57 @@
+=== tests/cases/compiler/argumentsAsPropertyName.ts ===
+// target: es5
+type MyType = {
+>MyType : MyType
+
+ arguments: Array
+>arguments : string[]
+>Array : T[]
+}
+
+declare function use(s: any);
+>use : (s: any) => any
+>s : any
+
+function myFunction(myType: MyType) {
+>myFunction : (myType: MyType) => void
+>myType : MyType
+>MyType : MyType
+
+ for (let i = 0; i < 10; i++) {
+>i : number
+>0 : 0
+>i < 10 : boolean
+>i : number
+>10 : 10
+>i++ : number
+>i : number
+
+ use(myType.arguments[i]);
+>use(myType.arguments[i]) : any
+>use : (s: any) => any
+>myType.arguments[i] : string
+>myType.arguments : string[]
+>myType : MyType
+>arguments : string[]
+>i : number
+
+ // create closure so that tsc will turn loop body into function
+ const x = 5;
+>x : 5
+>5 : 5
+
+ [1, 2, 3].forEach(function(j) { use(x); })
+>[1, 2, 3].forEach(function(j) { use(x); }) : void
+>[1, 2, 3].forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
+>[1, 2, 3] : number[]
+>1 : 1
+>2 : 2
+>3 : 3
+>forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
+>function(j) { use(x); } : (j: number) => void
+>j : number
+>use(x) : any
+>use : (s: any) => any
+>x : 5
+ }
+}
diff --git a/tests/baselines/reference/es3-jsx-preserve.js b/tests/baselines/reference/es3-jsx-preserve.js
new file mode 100644
index 00000000000..cb1ba2a887d
--- /dev/null
+++ b/tests/baselines/reference/es3-jsx-preserve.js
@@ -0,0 +1,11 @@
+//// [es3-jsx-preserve.tsx]
+
+const React: any = null;
+
+const elem = ;
+
+
+
+//// [es3-jsx-preserve.jsx]
+var React = null;
+var elem = ;
diff --git a/tests/baselines/reference/es3-jsx-preserve.symbols b/tests/baselines/reference/es3-jsx-preserve.symbols
new file mode 100644
index 00000000000..61c9260223f
--- /dev/null
+++ b/tests/baselines/reference/es3-jsx-preserve.symbols
@@ -0,0 +1,11 @@
+=== tests/cases/compiler/es3-jsx-preserve.tsx ===
+
+const React: any = null;
+>React : Symbol(React, Decl(es3-jsx-preserve.tsx, 1, 5))
+
+const elem = ;
+>elem : Symbol(elem, Decl(es3-jsx-preserve.tsx, 3, 5))
+>div : Symbol(unknown)
+>div : Symbol(unknown)
+
+
diff --git a/tests/baselines/reference/es3-jsx-preserve.types b/tests/baselines/reference/es3-jsx-preserve.types
new file mode 100644
index 00000000000..b37fe8af567
--- /dev/null
+++ b/tests/baselines/reference/es3-jsx-preserve.types
@@ -0,0 +1,13 @@
+=== tests/cases/compiler/es3-jsx-preserve.tsx ===
+
+const React: any = null;
+>React : any
+>null : null
+
+const elem = ;
+>elem : any
+> : any
+>div : any
+>div : any
+
+
diff --git a/tests/baselines/reference/es3-jsx-react-native.js b/tests/baselines/reference/es3-jsx-react-native.js
new file mode 100644
index 00000000000..08e6e25502b
--- /dev/null
+++ b/tests/baselines/reference/es3-jsx-react-native.js
@@ -0,0 +1,11 @@
+//// [es3-jsx-react-native.tsx]
+
+const React: any = null;
+
+const elem = ;
+
+
+
+//// [es3-jsx-react-native.js]
+var React = null;
+var elem = ;
diff --git a/tests/baselines/reference/es3-jsx-react-native.symbols b/tests/baselines/reference/es3-jsx-react-native.symbols
new file mode 100644
index 00000000000..e7f010bd2ea
--- /dev/null
+++ b/tests/baselines/reference/es3-jsx-react-native.symbols
@@ -0,0 +1,11 @@
+=== tests/cases/compiler/es3-jsx-react-native.tsx ===
+
+const React: any = null;
+>React : Symbol(React, Decl(es3-jsx-react-native.tsx, 1, 5))
+
+const elem = ;
+>elem : Symbol(elem, Decl(es3-jsx-react-native.tsx, 3, 5))
+>div : Symbol(unknown)
+>div : Symbol(unknown)
+
+
diff --git a/tests/baselines/reference/es3-jsx-react-native.types b/tests/baselines/reference/es3-jsx-react-native.types
new file mode 100644
index 00000000000..1bf199606f2
--- /dev/null
+++ b/tests/baselines/reference/es3-jsx-react-native.types
@@ -0,0 +1,13 @@
+=== tests/cases/compiler/es3-jsx-react-native.tsx ===
+
+const React: any = null;
+>React : any
+>null : null
+
+const elem = ;
+>elem : any
+> : any
+>div : any
+>div : any
+
+
diff --git a/tests/baselines/reference/es3-jsx-react.js b/tests/baselines/reference/es3-jsx-react.js
new file mode 100644
index 00000000000..861dde74c86
--- /dev/null
+++ b/tests/baselines/reference/es3-jsx-react.js
@@ -0,0 +1,11 @@
+//// [es3-jsx-react.tsx]
+
+const React: any = null;
+
+const elem = ;
+
+
+
+//// [es3-jsx-react.js]
+var React = null;
+var elem = React.createElement("div", null);
diff --git a/tests/baselines/reference/es3-jsx-react.symbols b/tests/baselines/reference/es3-jsx-react.symbols
new file mode 100644
index 00000000000..465cfab7ea9
--- /dev/null
+++ b/tests/baselines/reference/es3-jsx-react.symbols
@@ -0,0 +1,11 @@
+=== tests/cases/compiler/es3-jsx-react.tsx ===
+
+const React: any = null;
+>React : Symbol(React, Decl(es3-jsx-react.tsx, 1, 5))
+
+const elem = ;
+>elem : Symbol(elem, Decl(es3-jsx-react.tsx, 3, 5))
+>div : Symbol(unknown)
+>div : Symbol(unknown)
+
+
diff --git a/tests/baselines/reference/es3-jsx-react.types b/tests/baselines/reference/es3-jsx-react.types
new file mode 100644
index 00000000000..b7734ffc1f0
--- /dev/null
+++ b/tests/baselines/reference/es3-jsx-react.types
@@ -0,0 +1,13 @@
+=== tests/cases/compiler/es3-jsx-react.tsx ===
+
+const React: any = null;
+>React : any
+>null : null
+
+const elem = ;
+>elem : any
+> : any
+>div : any
+>div : any
+
+
diff --git a/tests/baselines/reference/interfaceExtendsObjectIntersection.js b/tests/baselines/reference/interfaceExtendsObjectIntersection.js
new file mode 100644
index 00000000000..a6fb62f5070
--- /dev/null
+++ b/tests/baselines/reference/interfaceExtendsObjectIntersection.js
@@ -0,0 +1,145 @@
+//// [interfaceExtendsObjectIntersection.ts]
+
+type T1 = { a: number };
+type T2 = T1 & { b: number };
+type T3 = () => void;
+type T4 = new () => { a: number };
+type T5 = number[];
+type T6 = [string, number];
+type T7 = { [P in 'a' | 'b' | 'c']: string };
+
+interface I1 extends T1 { x: string }
+interface I2 extends T2 { x: string }
+interface I3 extends T3 { x: string }
+interface I4 extends T4 { x: string }
+interface I5 extends T5 { x: string }
+interface I6 extends T6 { x: string }
+interface I7 extends T7 { x: string }
+
+type Constructor = new () => T;
+declare function Constructor(): Constructor;
+
+class C1 extends Constructor() { x: string }
+class C2 extends Constructor() { x: string }
+class C3 extends Constructor() { x: string }
+class C4 extends Constructor() { x: string }
+class C5 extends Constructor() { x: string }
+class C6 extends Constructor() { x: string }
+class C7 extends Constructor() { x: string }
+
+declare function fx(x: string): string;
+declare class CX { a: number }
+declare enum EX { A, B, C }
+declare namespace NX { export const a = 1 }
+
+type T10 = typeof fx;
+type T11 = typeof CX;
+type T12 = typeof EX;
+type T13 = typeof NX;
+
+interface I10 extends T10 { x: string }
+interface I11 extends T11 { x: string }
+interface I12 extends T12 { x: string }
+interface I13 extends T13 { x: string }
+
+type Identifiable = { _id: string } & T;
+
+interface I20 extends Partial { x: string }
+interface I21 extends Readonly { x: string }
+interface I22 extends Identifiable { x: string }
+interface I23 extends Identifiable { x: string }
+
+class C20 extends Constructor>() { x: string }
+class C21 extends Constructor>() { x: string }
+class C22 extends Constructor>() { x: string }
+class C23 extends Constructor>() { x: string }
+
+
+//// [interfaceExtendsObjectIntersection.js]
+var __extends = (this && this.__extends) || (function () {
+ var 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 function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+var C1 = (function (_super) {
+ __extends(C1, _super);
+ function C1() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C1;
+}(Constructor()));
+var C2 = (function (_super) {
+ __extends(C2, _super);
+ function C2() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C2;
+}(Constructor()));
+var C3 = (function (_super) {
+ __extends(C3, _super);
+ function C3() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C3;
+}(Constructor()));
+var C4 = (function (_super) {
+ __extends(C4, _super);
+ function C4() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C4;
+}(Constructor()));
+var C5 = (function (_super) {
+ __extends(C5, _super);
+ function C5() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C5;
+}(Constructor()));
+var C6 = (function (_super) {
+ __extends(C6, _super);
+ function C6() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C6;
+}(Constructor()));
+var C7 = (function (_super) {
+ __extends(C7, _super);
+ function C7() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C7;
+}(Constructor()));
+var C20 = (function (_super) {
+ __extends(C20, _super);
+ function C20() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C20;
+}(Constructor()));
+var C21 = (function (_super) {
+ __extends(C21, _super);
+ function C21() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C21;
+}(Constructor()));
+var C22 = (function (_super) {
+ __extends(C22, _super);
+ function C22() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C22;
+}(Constructor()));
+var C23 = (function (_super) {
+ __extends(C23, _super);
+ function C23() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C23;
+}(Constructor()));
diff --git a/tests/baselines/reference/interfaceExtendsObjectIntersection.symbols b/tests/baselines/reference/interfaceExtendsObjectIntersection.symbols
new file mode 100644
index 00000000000..16c8c51cf47
--- /dev/null
+++ b/tests/baselines/reference/interfaceExtendsObjectIntersection.symbols
@@ -0,0 +1,230 @@
+=== tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersection.ts ===
+
+type T1 = { a: number };
+>T1 : Symbol(T1, Decl(interfaceExtendsObjectIntersection.ts, 0, 0))
+>a : Symbol(a, Decl(interfaceExtendsObjectIntersection.ts, 1, 11))
+
+type T2 = T1 & { b: number };
+>T2 : Symbol(T2, Decl(interfaceExtendsObjectIntersection.ts, 1, 24))
+>T1 : Symbol(T1, Decl(interfaceExtendsObjectIntersection.ts, 0, 0))
+>b : Symbol(b, Decl(interfaceExtendsObjectIntersection.ts, 2, 16))
+
+type T3 = () => void;
+>T3 : Symbol(T3, Decl(interfaceExtendsObjectIntersection.ts, 2, 29))
+
+type T4 = new () => { a: number };
+>T4 : Symbol(T4, Decl(interfaceExtendsObjectIntersection.ts, 3, 21))
+>a : Symbol(a, Decl(interfaceExtendsObjectIntersection.ts, 4, 21))
+
+type T5 = number[];
+>T5 : Symbol(T5, Decl(interfaceExtendsObjectIntersection.ts, 4, 34))
+
+type T6 = [string, number];
+>T6 : Symbol(T6, Decl(interfaceExtendsObjectIntersection.ts, 5, 19))
+
+type T7 = { [P in 'a' | 'b' | 'c']: string };
+>T7 : Symbol(T7, Decl(interfaceExtendsObjectIntersection.ts, 6, 27))
+>P : Symbol(P, Decl(interfaceExtendsObjectIntersection.ts, 7, 13))
+
+interface I1 extends T1 { x: string }
+>I1 : Symbol(I1, Decl(interfaceExtendsObjectIntersection.ts, 7, 45))
+>T1 : Symbol(T1, Decl(interfaceExtendsObjectIntersection.ts, 0, 0))
+>x : Symbol(I1.x, Decl(interfaceExtendsObjectIntersection.ts, 9, 25))
+
+interface I2 extends T2 { x: string }
+>I2 : Symbol(I2, Decl(interfaceExtendsObjectIntersection.ts, 9, 37))
+>T2 : Symbol(T2, Decl(interfaceExtendsObjectIntersection.ts, 1, 24))
+>x : Symbol(I2.x, Decl(interfaceExtendsObjectIntersection.ts, 10, 25))
+
+interface I3 extends T3 { x: string }
+>I3 : Symbol(I3, Decl(interfaceExtendsObjectIntersection.ts, 10, 37))
+>T3 : Symbol(T3, Decl(interfaceExtendsObjectIntersection.ts, 2, 29))
+>x : Symbol(I3.x, Decl(interfaceExtendsObjectIntersection.ts, 11, 25))
+
+interface I4 extends T4 { x: string }
+>I4 : Symbol(I4, Decl(interfaceExtendsObjectIntersection.ts, 11, 37))
+>T4 : Symbol(T4, Decl(interfaceExtendsObjectIntersection.ts, 3, 21))
+>x : Symbol(I4.x, Decl(interfaceExtendsObjectIntersection.ts, 12, 25))
+
+interface I5 extends T5 { x: string }
+>I5 : Symbol(I5, Decl(interfaceExtendsObjectIntersection.ts, 12, 37))
+>T5 : Symbol(T5, Decl(interfaceExtendsObjectIntersection.ts, 4, 34))
+>x : Symbol(I5.x, Decl(interfaceExtendsObjectIntersection.ts, 13, 25))
+
+interface I6 extends T6 { x: string }
+>I6 : Symbol(I6, Decl(interfaceExtendsObjectIntersection.ts, 13, 37))
+>T6 : Symbol(T6, Decl(interfaceExtendsObjectIntersection.ts, 5, 19))
+>x : Symbol(I6.x, Decl(interfaceExtendsObjectIntersection.ts, 14, 25))
+
+interface I7 extends T7 { x: string }
+>I7 : Symbol(I7, Decl(interfaceExtendsObjectIntersection.ts, 14, 37))
+>T7 : Symbol(T7, Decl(interfaceExtendsObjectIntersection.ts, 6, 27))
+>x : Symbol(I7.x, Decl(interfaceExtendsObjectIntersection.ts, 15, 25))
+
+type Constructor = new () => T;
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>T : Symbol(T, Decl(interfaceExtendsObjectIntersection.ts, 17, 17))
+>T : Symbol(T, Decl(interfaceExtendsObjectIntersection.ts, 17, 17))
+
+declare function Constructor(): Constructor;
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>T : Symbol(T, Decl(interfaceExtendsObjectIntersection.ts, 18, 29))
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>T : Symbol(T, Decl(interfaceExtendsObjectIntersection.ts, 18, 29))
+
+class C1 extends Constructor() { x: string }
+>C1 : Symbol(C1, Decl(interfaceExtendsObjectIntersection.ts, 18, 50))
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>I1 : Symbol(I1, Decl(interfaceExtendsObjectIntersection.ts, 7, 45))
+>x : Symbol(C1.x, Decl(interfaceExtendsObjectIntersection.ts, 20, 36))
+
+class C2 extends Constructor() { x: string }
+>C2 : Symbol(C2, Decl(interfaceExtendsObjectIntersection.ts, 20, 48))
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>I2 : Symbol(I2, Decl(interfaceExtendsObjectIntersection.ts, 9, 37))
+>x : Symbol(C2.x, Decl(interfaceExtendsObjectIntersection.ts, 21, 36))
+
+class C3 extends Constructor() { x: string }
+>C3 : Symbol(C3, Decl(interfaceExtendsObjectIntersection.ts, 21, 48))
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>I3 : Symbol(I3, Decl(interfaceExtendsObjectIntersection.ts, 10, 37))
+>x : Symbol(C3.x, Decl(interfaceExtendsObjectIntersection.ts, 22, 36))
+
+class C4 extends Constructor() { x: string }
+>C4 : Symbol(C4, Decl(interfaceExtendsObjectIntersection.ts, 22, 48))
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>I4 : Symbol(I4, Decl(interfaceExtendsObjectIntersection.ts, 11, 37))
+>x : Symbol(C4.x, Decl(interfaceExtendsObjectIntersection.ts, 23, 36))
+
+class C5 extends Constructor() { x: string }
+>C5 : Symbol(C5, Decl(interfaceExtendsObjectIntersection.ts, 23, 48))
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>I5 : Symbol(I5, Decl(interfaceExtendsObjectIntersection.ts, 12, 37))
+>x : Symbol(C5.x, Decl(interfaceExtendsObjectIntersection.ts, 24, 36))
+
+class C6 extends Constructor() { x: string }
+>C6 : Symbol(C6, Decl(interfaceExtendsObjectIntersection.ts, 24, 48))
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>I6 : Symbol(I6, Decl(interfaceExtendsObjectIntersection.ts, 13, 37))
+>x : Symbol(C6.x, Decl(interfaceExtendsObjectIntersection.ts, 25, 36))
+
+class C7 extends Constructor() { x: string }
+>C7 : Symbol(C7, Decl(interfaceExtendsObjectIntersection.ts, 25, 48))
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>I7 : Symbol(I7, Decl(interfaceExtendsObjectIntersection.ts, 14, 37))
+>x : Symbol(C7.x, Decl(interfaceExtendsObjectIntersection.ts, 26, 36))
+
+declare function fx(x: string): string;
+>fx : Symbol(fx, Decl(interfaceExtendsObjectIntersection.ts, 26, 48))
+>x : Symbol(x, Decl(interfaceExtendsObjectIntersection.ts, 28, 20))
+
+declare class CX { a: number }
+>CX : Symbol(CX, Decl(interfaceExtendsObjectIntersection.ts, 28, 39))
+>a : Symbol(CX.a, Decl(interfaceExtendsObjectIntersection.ts, 29, 18))
+
+declare enum EX { A, B, C }
+>EX : Symbol(EX, Decl(interfaceExtendsObjectIntersection.ts, 29, 30))
+>A : Symbol(EX.A, Decl(interfaceExtendsObjectIntersection.ts, 30, 17))
+>B : Symbol(EX.B, Decl(interfaceExtendsObjectIntersection.ts, 30, 20))
+>C : Symbol(EX.C, Decl(interfaceExtendsObjectIntersection.ts, 30, 23))
+
+declare namespace NX { export const a = 1 }
+>NX : Symbol(NX, Decl(interfaceExtendsObjectIntersection.ts, 30, 27))
+>a : Symbol(a, Decl(interfaceExtendsObjectIntersection.ts, 31, 35))
+
+type T10 = typeof fx;
+>T10 : Symbol(T10, Decl(interfaceExtendsObjectIntersection.ts, 31, 43))
+>fx : Symbol(fx, Decl(interfaceExtendsObjectIntersection.ts, 26, 48))
+
+type T11 = typeof CX;
+>T11 : Symbol(T11, Decl(interfaceExtendsObjectIntersection.ts, 33, 21))
+>CX : Symbol(CX, Decl(interfaceExtendsObjectIntersection.ts, 28, 39))
+
+type T12 = typeof EX;
+>T12 : Symbol(T12, Decl(interfaceExtendsObjectIntersection.ts, 34, 21))
+>EX : Symbol(EX, Decl(interfaceExtendsObjectIntersection.ts, 29, 30))
+
+type T13 = typeof NX;
+>T13 : Symbol(T13, Decl(interfaceExtendsObjectIntersection.ts, 35, 21))
+>NX : Symbol(NX, Decl(interfaceExtendsObjectIntersection.ts, 30, 27))
+
+interface I10 extends T10 { x: string }
+>I10 : Symbol(I10, Decl(interfaceExtendsObjectIntersection.ts, 36, 21))
+>T10 : Symbol(T10, Decl(interfaceExtendsObjectIntersection.ts, 31, 43))
+>x : Symbol(I10.x, Decl(interfaceExtendsObjectIntersection.ts, 38, 27))
+
+interface I11 extends T11 { x: string }
+>I11 : Symbol(I11, Decl(interfaceExtendsObjectIntersection.ts, 38, 39))
+>T11 : Symbol(T11, Decl(interfaceExtendsObjectIntersection.ts, 33, 21))
+>x : Symbol(I11.x, Decl(interfaceExtendsObjectIntersection.ts, 39, 27))
+
+interface I12 extends T12 { x: string }
+>I12 : Symbol(I12, Decl(interfaceExtendsObjectIntersection.ts, 39, 39))
+>T12 : Symbol(T12, Decl(interfaceExtendsObjectIntersection.ts, 34, 21))
+>x : Symbol(I12.x, Decl(interfaceExtendsObjectIntersection.ts, 40, 27))
+
+interface I13 extends T13 { x: string }
+>I13 : Symbol(I13, Decl(interfaceExtendsObjectIntersection.ts, 40, 39))
+>T13 : Symbol(T13, Decl(interfaceExtendsObjectIntersection.ts, 35, 21))
+>x : Symbol(I13.x, Decl(interfaceExtendsObjectIntersection.ts, 41, 27))
+
+type Identifiable = { _id: string } & T;
+>Identifiable : Symbol(Identifiable, Decl(interfaceExtendsObjectIntersection.ts, 41, 39))
+>T : Symbol(T, Decl(interfaceExtendsObjectIntersection.ts, 43, 18))
+>_id : Symbol(_id, Decl(interfaceExtendsObjectIntersection.ts, 43, 24))
+>T : Symbol(T, Decl(interfaceExtendsObjectIntersection.ts, 43, 18))
+
+interface I20 extends Partial { x: string }
+>I20 : Symbol(I20, Decl(interfaceExtendsObjectIntersection.ts, 43, 43))
+>Partial : Symbol(Partial, Decl(lib.d.ts, --, --))
+>T1 : Symbol(T1, Decl(interfaceExtendsObjectIntersection.ts, 0, 0))
+>x : Symbol(I20.x, Decl(interfaceExtendsObjectIntersection.ts, 45, 35))
+
+interface I21 extends Readonly { x: string }
+>I21 : Symbol(I21, Decl(interfaceExtendsObjectIntersection.ts, 45, 47))
+>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --))
+>T1 : Symbol(T1, Decl(interfaceExtendsObjectIntersection.ts, 0, 0))
+>x : Symbol(I21.x, Decl(interfaceExtendsObjectIntersection.ts, 46, 36))
+
+interface I22 extends Identifiable { x: string }
+>I22 : Symbol(I22, Decl(interfaceExtendsObjectIntersection.ts, 46, 48))
+>Identifiable : Symbol(Identifiable, Decl(interfaceExtendsObjectIntersection.ts, 41, 39))
+>T1 : Symbol(T1, Decl(interfaceExtendsObjectIntersection.ts, 0, 0))
+>x : Symbol(I22.x, Decl(interfaceExtendsObjectIntersection.ts, 47, 40))
+
+interface I23 extends Identifiable { x: string }
+>I23 : Symbol(I23, Decl(interfaceExtendsObjectIntersection.ts, 47, 52))
+>Identifiable : Symbol(Identifiable, Decl(interfaceExtendsObjectIntersection.ts, 41, 39))
+>T1 : Symbol(T1, Decl(interfaceExtendsObjectIntersection.ts, 0, 0))
+>b : Symbol(b, Decl(interfaceExtendsObjectIntersection.ts, 48, 41))
+>x : Symbol(I23.x, Decl(interfaceExtendsObjectIntersection.ts, 48, 55))
+
+class C20 extends Constructor>() { x: string }
+>C20 : Symbol(C20, Decl(interfaceExtendsObjectIntersection.ts, 48, 67))
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>Partial : Symbol(Partial, Decl(lib.d.ts, --, --))
+>T1 : Symbol(T1, Decl(interfaceExtendsObjectIntersection.ts, 0, 0))
+>x : Symbol(C20.x, Decl(interfaceExtendsObjectIntersection.ts, 50, 46))
+
+class C21 extends Constructor>() { x: string }
+>C21 : Symbol(C21, Decl(interfaceExtendsObjectIntersection.ts, 50, 58))
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --))
+>T1 : Symbol(T1, Decl(interfaceExtendsObjectIntersection.ts, 0, 0))
+>x : Symbol(C21.x, Decl(interfaceExtendsObjectIntersection.ts, 51, 47))
+
+class C22 extends Constructor>() { x: string }
+>C22 : Symbol(C22, Decl(interfaceExtendsObjectIntersection.ts, 51, 59))
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>Identifiable : Symbol(Identifiable, Decl(interfaceExtendsObjectIntersection.ts, 41, 39))
+>T1 : Symbol(T1, Decl(interfaceExtendsObjectIntersection.ts, 0, 0))
+>x : Symbol(C22.x, Decl(interfaceExtendsObjectIntersection.ts, 52, 51))
+
+class C23 extends Constructor>() { x: string }
+>C23 : Symbol(C23, Decl(interfaceExtendsObjectIntersection.ts, 52, 63))
+>Constructor : Symbol(Constructor, Decl(interfaceExtendsObjectIntersection.ts, 15, 37), Decl(interfaceExtendsObjectIntersection.ts, 17, 34))
+>Identifiable : Symbol(Identifiable, Decl(interfaceExtendsObjectIntersection.ts, 41, 39))
+>T1 : Symbol(T1, Decl(interfaceExtendsObjectIntersection.ts, 0, 0))
+>b : Symbol(b, Decl(interfaceExtendsObjectIntersection.ts, 53, 49))
+>x : Symbol(C23.x, Decl(interfaceExtendsObjectIntersection.ts, 53, 66))
+
diff --git a/tests/baselines/reference/interfaceExtendsObjectIntersection.types b/tests/baselines/reference/interfaceExtendsObjectIntersection.types
new file mode 100644
index 00000000000..1ff550df7b4
--- /dev/null
+++ b/tests/baselines/reference/interfaceExtendsObjectIntersection.types
@@ -0,0 +1,242 @@
+=== tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersection.ts ===
+
+type T1 = { a: number };
+>T1 : T1
+>a : number
+
+type T2 = T1 & { b: number };
+>T2 : T2
+>T1 : T1
+>b : number
+
+type T3 = () => void;
+>T3 : T3
+
+type T4 = new () => { a: number };
+>T4 : T4
+>a : number
+
+type T5 = number[];
+>T5 : number[]
+
+type T6 = [string, number];
+>T6 : [string, number]
+
+type T7 = { [P in 'a' | 'b' | 'c']: string };
+>T7 : T7
+>P : P
+
+interface I1 extends T1 { x: string }
+>I1 : I1
+>T1 : T1
+>x : string
+
+interface I2 extends T2 { x: string }
+>I2 : I2
+>T2 : T2
+>x : string
+
+interface I3 extends T3 { x: string }
+>I3 : I3
+>T3 : T3
+>x : string
+
+interface I4 extends T4 { x: string }
+>I4 : I4
+>T4 : T4
+>x : string
+
+interface I5 extends T5 { x: string }
+>I5 : I5
+>T5 : number[]
+>x : string
+
+interface I6 extends T6 { x: string }
+>I6 : I6
+>T6 : [string, number]
+>x : string
+
+interface I7 extends T7 { x: string }
+>I7 : I7
+>T7 : T7
+>x : string
+
+type Constructor = new () => T;
+>Constructor : Constructor
+>T : T
+>T : T
+
+declare function Constructor(): Constructor;
+>Constructor : () => Constructor
+>T : T
+>Constructor : Constructor
+>T : T
+
+class C1 extends Constructor() { x: string }
+>C1 : C1
+>Constructor() : I1
+>Constructor : () => Constructor
+>I1 : I1
+>x : string
+
+class C2 extends Constructor() { x: string }
+>C2 : C2
+>Constructor() : I2
+>Constructor : () => Constructor
+>I2 : I2
+>x : string
+
+class C3 extends Constructor() { x: string }
+>C3 : C3
+>Constructor() : I3
+>Constructor : () => Constructor
+>I3 : I3
+>x : string
+
+class C4 extends Constructor() { x: string }
+>C4 : C4
+>Constructor() : I4
+>Constructor : () => Constructor
+>I4 : I4
+>x : string
+
+class C5 extends Constructor() { x: string }
+>C5 : C5
+>Constructor() : I5
+>Constructor : () => Constructor
+>I5 : I5
+>x : string
+
+class C6 extends Constructor() { x: string }
+>C6 : C6
+>Constructor() : I6
+>Constructor : () => Constructor
+>I6 : I6
+>x : string
+
+class C7 extends Constructor() { x: string }
+>C7 : C7
+>Constructor() : I7
+>Constructor : () => Constructor
+>I7 : I7
+>x : string
+
+declare function fx(x: string): string;
+>fx : (x: string) => string
+>x : string
+
+declare class CX { a: number }
+>CX : CX
+>a : number
+
+declare enum EX { A, B, C }
+>EX : EX
+>A : EX
+>B : EX
+>C : EX
+
+declare namespace NX { export const a = 1 }
+>NX : typeof NX
+>a : 1
+>1 : 1
+
+type T10 = typeof fx;
+>T10 : (x: string) => string
+>fx : (x: string) => string
+
+type T11 = typeof CX;
+>T11 : typeof CX
+>CX : typeof CX
+
+type T12 = typeof EX;
+>T12 : typeof EX
+>EX : typeof EX
+
+type T13 = typeof NX;
+>T13 : typeof NX
+>NX : typeof NX
+
+interface I10 extends T10 { x: string }
+>I10 : I10
+>T10 : (x: string) => string
+>x : string
+
+interface I11 extends T11 { x: string }
+>I11 : I11
+>T11 : typeof CX
+>x : string
+
+interface I12 extends T12 { x: string }
+>I12 : I12
+>T12 : typeof EX
+>x : string
+
+interface I13 extends T13 { x: string }
+>I13 : I13
+>T13 : typeof NX
+>x : string
+
+type Identifiable = { _id: string } & T;
+>Identifiable : Identifiable
+>T : T
+>_id : string
+>T : T
+
+interface I20 extends Partial { x: string }
+>I20 : I20
+>Partial : Partial
+>T1 : T1
+>x : string
+
+interface I21 extends Readonly { x: string }
+>I21 : I21
+>Readonly : Readonly
+>T1 : T1
+>x : string
+
+interface I22 extends Identifiable { x: string }
+>I22 : I22
+>Identifiable : Identifiable
+>T1 : T1
+>x : string
+
+interface I23 extends Identifiable { x: string }
+>I23 : I23
+>Identifiable : Identifiable
+>T1 : T1
+>b : number
+>x : string
+
+class C20 extends Constructor>() { x: string }
+>C20 : C20
+>Constructor>() : Partial
+>Constructor : () => Constructor
+>Partial : Partial
+>T1 : T1
+>x : string
+
+class C21 extends Constructor>() { x: string }
+>C21 : C21
+>Constructor>() : Readonly
+>Constructor : () => Constructor
+>Readonly : Readonly
+>T1 : T1
+>x : string
+
+class C22 extends Constructor>() { x: string }
+>C22 : C22
+>Constructor>() : Identifiable
+>Constructor : () => Constructor
+>Identifiable : Identifiable
+>T1 : T1
+>x : string
+
+class C23 extends Constructor>() { x: string }
+>C23 : C23
+>Constructor>() : Identifiable
+>Constructor : () => Constructor
+>Identifiable : Identifiable
+>T1 : T1
+>b : number
+>x : string
+
diff --git a/tests/baselines/reference/interfaceExtendsObjectIntersectionErrors.errors.txt b/tests/baselines/reference/interfaceExtendsObjectIntersectionErrors.errors.txt
new file mode 100644
index 00000000000..839474b3bdc
--- /dev/null
+++ b/tests/baselines/reference/interfaceExtendsObjectIntersectionErrors.errors.txt
@@ -0,0 +1,197 @@
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(8,11): error TS2430: Interface 'I1' incorrectly extends interface 'T1'.
+ Types of property 'a' are incompatible.
+ Type 'string' is not assignable to type 'number'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(9,11): error TS2430: Interface 'I2' incorrectly extends interface 'T2'.
+ Type 'I2' is not assignable to type '{ b: number; }'.
+ Types of property 'b' are incompatible.
+ Type 'string' is not assignable to type 'number'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(10,11): error TS2430: Interface 'I3' incorrectly extends interface 'number[]'.
+ Types of property 'length' are incompatible.
+ Type 'string' is not assignable to type 'number'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(11,11): error TS2430: Interface 'I4' incorrectly extends interface '[string, number]'.
+ Types of property '0' are incompatible.
+ Type 'number' is not assignable to type 'string'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(12,11): error TS2430: Interface 'I5' incorrectly extends interface 'T5'.
+ Types of property 'c' are incompatible.
+ Type 'number' is not assignable to type 'string'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(17,7): error TS2415: Class 'C1' incorrectly extends base class 'T1'.
+ Types of property 'a' are incompatible.
+ Type 'string' is not assignable to type 'number'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(18,7): error TS2415: Class 'C2' incorrectly extends base class 'T2'.
+ Type 'C2' is not assignable to type '{ b: number; }'.
+ Types of property 'b' are incompatible.
+ Type 'string' is not assignable to type 'number'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(19,7): error TS2415: Class 'C3' incorrectly extends base class 'number[]'.
+ Types of property 'length' are incompatible.
+ Type 'string' is not assignable to type 'number'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(20,7): error TS2415: Class 'C4' incorrectly extends base class '[string, number]'.
+ Types of property '0' are incompatible.
+ Type 'number' is not assignable to type 'string'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(21,7): error TS2415: Class 'C5' incorrectly extends base class 'T5'.
+ Types of property 'c' are incompatible.
+ Type 'number' is not assignable to type 'string'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(31,11): error TS2430: Interface 'I10' incorrectly extends interface 'typeof CX'.
+ Types of property 'a' are incompatible.
+ Type 'number' is not assignable to type 'string'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(32,11): error TS2430: Interface 'I11' incorrectly extends interface 'typeof EX'.
+ Types of property 'C' are incompatible.
+ Type 'string' is not assignable to type 'EX'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(33,11): error TS2430: Interface 'I12' incorrectly extends interface 'typeof NX'.
+ Types of property 'a' are incompatible.
+ Type 'number' is not assignable to type '"hello"'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(34,29): error TS2411: Property 'a' of type 'string' is not assignable to string index type 'number'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(34,29): error TS2411: Property 'prototype' of type 'CX' is not assignable to string index type 'number'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(35,29): error TS2413: Numeric index type 'string' is not assignable to string index type 'number'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(36,29): error TS2411: Property 'a' of type '"hello"' is not assignable to string index type 'number'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(40,11): error TS2430: Interface 'I20' incorrectly extends interface 'Partial'.
+ Types of property 'a' are incompatible.
+ Type 'string' is not assignable to type 'number | undefined'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(41,11): error TS2430: Interface 'I21' incorrectly extends interface 'Readonly'.
+ Types of property 'a' are incompatible.
+ Type 'string' is not assignable to type 'number'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(42,11): error TS2430: Interface 'I22' incorrectly extends interface 'Identifiable'.
+ Type 'I22' is not assignable to type 'T1'.
+ Types of property 'a' are incompatible.
+ Type 'string' is not assignable to type 'number'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(43,11): error TS2430: Interface 'I23' incorrectly extends interface 'Identifiable'.
+ Type 'I23' is not assignable to type 'T1'.
+ Types of property 'a' are incompatible.
+ Type 'string' is not assignable to type 'number'.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(47,23): error TS2312: An interface may only extend a class or another interface.
+tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts(48,26): error TS2312: An interface may only extend a class or another interface.
+
+
+==== tests/cases/conformance/interfaces/interfaceDeclarations/interfaceExtendsObjectIntersectionErrors.ts (23 errors) ====
+
+ type T1 = { a: number };
+ type T2 = T1 & { b: number };
+ type T3 = number[];
+ type T4 = [string, number];
+ type T5 = { [P in 'a' | 'b' | 'c']: string };
+
+ interface I1 extends T1 { a: string }
+ ~~
+!!! error TS2430: Interface 'I1' incorrectly extends interface 'T1'.
+!!! error TS2430: Types of property 'a' are incompatible.
+!!! error TS2430: Type 'string' is not assignable to type 'number'.
+ interface I2 extends T2 { b: string }
+ ~~
+!!! error TS2430: Interface 'I2' incorrectly extends interface 'T2'.
+!!! error TS2430: Type 'I2' is not assignable to type '{ b: number; }'.
+!!! error TS2430: Types of property 'b' are incompatible.
+!!! error TS2430: Type 'string' is not assignable to type 'number'.
+ interface I3 extends T3 { length: string }
+ ~~
+!!! error TS2430: Interface 'I3' incorrectly extends interface 'number[]'.
+!!! error TS2430: Types of property 'length' are incompatible.
+!!! error TS2430: Type 'string' is not assignable to type 'number'.
+ interface I4 extends T4 { 0: number }
+ ~~
+!!! error TS2430: Interface 'I4' incorrectly extends interface '[string, number]'.
+!!! error TS2430: Types of property '0' are incompatible.
+!!! error TS2430: Type 'number' is not assignable to type 'string'.
+ interface I5 extends T5 { c: number }
+ ~~
+!!! error TS2430: Interface 'I5' incorrectly extends interface 'T5'.
+!!! error TS2430: Types of property 'c' are incompatible.
+!!! error TS2430: Type 'number' is not assignable to type 'string'.
+
+ type Constructor = new () => T;
+ declare function Constructor(): Constructor;
+
+ class C1 extends Constructor() { a: string }
+ ~~
+!!! error TS2415: Class 'C1' incorrectly extends base class 'T1'.
+!!! error TS2415: Types of property 'a' are incompatible.
+!!! error TS2415: Type 'string' is not assignable to type 'number'.
+ class C2 extends Constructor() { b: string }
+ ~~
+!!! error TS2415: Class 'C2' incorrectly extends base class 'T2'.
+!!! error TS2415: Type 'C2' is not assignable to type '{ b: number; }'.
+!!! error TS2415: Types of property 'b' are incompatible.
+!!! error TS2415: Type 'string' is not assignable to type 'number'.
+ class C3 extends Constructor() { length: string }
+ ~~
+!!! error TS2415: Class 'C3' incorrectly extends base class 'number[]'.
+!!! error TS2415: Types of property 'length' are incompatible.
+!!! error TS2415: Type 'string' is not assignable to type 'number'.
+ class C4 extends Constructor() { 0: number }
+ ~~
+!!! error TS2415: Class 'C4' incorrectly extends base class '[string, number]'.
+!!! error TS2415: Types of property '0' are incompatible.
+!!! error TS2415: Type 'number' is not assignable to type 'string'.
+ class C5 extends Constructor() { c: number }
+ ~~
+!!! error TS2415: Class 'C5' incorrectly extends base class 'T5'.
+!!! error TS2415: Types of property 'c' are incompatible.
+!!! error TS2415: Type 'number' is not assignable to type 'string'.
+
+ declare class CX { static a: string }
+ declare enum EX { A, B, C }
+ declare namespace NX { export const a = "hello" }
+
+ type TCX = typeof CX;
+ type TEX = typeof EX;
+ type TNX = typeof NX;
+
+ interface I10 extends TCX { a: number }
+ ~~~
+!!! error TS2430: Interface 'I10' incorrectly extends interface 'typeof CX'.
+!!! error TS2430: Types of property 'a' are incompatible.
+!!! error TS2430: Type 'number' is not assignable to type 'string'.
+ interface I11 extends TEX { C: string }
+ ~~~
+!!! error TS2430: Interface 'I11' incorrectly extends interface 'typeof EX'.
+!!! error TS2430: Types of property 'C' are incompatible.
+!!! error TS2430: Type 'string' is not assignable to type 'EX'.
+ interface I12 extends TNX { a: number }
+ ~~~
+!!! error TS2430: Interface 'I12' incorrectly extends interface 'typeof NX'.
+!!! error TS2430: Types of property 'a' are incompatible.
+!!! error TS2430: Type 'number' is not assignable to type '"hello"'.
+ interface I14 extends TCX { [x: string]: number }
+ ~~~~~~~~~~~~~~~~~~~
+!!! error TS2411: Property 'a' of type 'string' is not assignable to string index type 'number'.
+ ~~~~~~~~~~~~~~~~~~~
+!!! error TS2411: Property 'prototype' of type 'CX' is not assignable to string index type 'number'.
+ interface I15 extends TEX { [x: string]: number }
+ ~~~~~~~~~~~~~~~~~~~
+!!! error TS2413: Numeric index type 'string' is not assignable to string index type 'number'.
+ interface I16 extends TNX { [x: string]: number }
+ ~~~~~~~~~~~~~~~~~~~
+!!! error TS2411: Property 'a' of type '"hello"' is not assignable to string index type 'number'.
+
+ type Identifiable = { _id: string } & T;
+
+ interface I20 extends Partial { a: string }
+ ~~~
+!!! error TS2430: Interface 'I20' incorrectly extends interface 'Partial'.
+!!! error TS2430: Types of property 'a' are incompatible.
+!!! error TS2430: Type 'string' is not assignable to type 'number | undefined'.
+ interface I21 extends Readonly { a: string }
+ ~~~
+!!! error TS2430: Interface 'I21' incorrectly extends interface 'Readonly'.
+!!! error TS2430: Types of property 'a' are incompatible.
+!!! error TS2430: Type 'string' is not assignable to type 'number'.
+ interface I22 extends Identifiable { a: string }
+ ~~~
+!!! error TS2430: Interface 'I22' incorrectly extends interface 'Identifiable'.
+!!! error TS2430: Type 'I22' is not assignable to type 'T1'.
+!!! error TS2430: Types of property 'a' are incompatible.
+!!! error TS2430: Type 'string' is not assignable to type 'number'.
+ interface I23 extends Identifiable { a: string }
+ ~~~
+!!! error TS2430: Interface 'I23' incorrectly extends interface 'Identifiable'.
+!!! error TS2430: Type 'I23' is not assignable to type 'T1'.
+!!! error TS2430: Types of property 'a' are incompatible.
+!!! error TS2430: Type 'string' is not assignable to type 'number'.
+
+ type U = { a: number } | { b: string };
+
+ interface I30 extends U { x: string }
+ ~
+!!! error TS2312: An interface may only extend a class or another interface.
+ interface I31 extends T { x: string }
+ ~
+!!! error TS2312: An interface may only extend a class or another interface.
+
\ No newline at end of file
diff --git a/tests/baselines/reference/interfaceExtendsObjectIntersectionErrors.js b/tests/baselines/reference/interfaceExtendsObjectIntersectionErrors.js
new file mode 100644
index 00000000000..61f84b2f7fe
--- /dev/null
+++ b/tests/baselines/reference/interfaceExtendsObjectIntersectionErrors.js
@@ -0,0 +1,97 @@
+//// [interfaceExtendsObjectIntersectionErrors.ts]
+
+type T1 = { a: number };
+type T2 = T1 & { b: number };
+type T3 = number[];
+type T4 = [string, number];
+type T5 = { [P in 'a' | 'b' | 'c']: string };
+
+interface I1 extends T1 { a: string }
+interface I2 extends T2 { b: string }
+interface I3 extends T3 { length: string }
+interface I4 extends T4 { 0: number }
+interface I5 extends T5 { c: number }
+
+type Constructor = new () => T;
+declare function Constructor(): Constructor;
+
+class C1 extends Constructor() { a: string }
+class C2 extends Constructor() { b: string }
+class C3 extends Constructor() { length: string }
+class C4 extends Constructor() { 0: number }
+class C5 extends Constructor() { c: number }
+
+declare class CX { static a: string }
+declare enum EX { A, B, C }
+declare namespace NX { export const a = "hello" }
+
+type TCX = typeof CX;
+type TEX = typeof EX;
+type TNX = typeof NX;
+
+interface I10 extends TCX { a: number }
+interface I11 extends TEX { C: string }
+interface I12 extends TNX { a: number }
+interface I14 extends TCX { [x: string]: number }
+interface I15 extends TEX { [x: string]: number }
+interface I16 extends TNX { [x: string]: number }
+
+type Identifiable = { _id: string } & T;
+
+interface I20 extends Partial { a: string }
+interface I21 extends Readonly { a: string }
+interface I22 extends Identifiable { a: string }
+interface I23 extends Identifiable { a: string }
+
+type U = { a: number } | { b: string };
+
+interface I30 extends U { x: string }
+interface I31 extends T { x: string }
+
+
+//// [interfaceExtendsObjectIntersectionErrors.js]
+var __extends = (this && this.__extends) || (function () {
+ var 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 function (d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+})();
+var C1 = (function (_super) {
+ __extends(C1, _super);
+ function C1() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C1;
+}(Constructor()));
+var C2 = (function (_super) {
+ __extends(C2, _super);
+ function C2() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C2;
+}(Constructor()));
+var C3 = (function (_super) {
+ __extends(C3, _super);
+ function C3() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C3;
+}(Constructor()));
+var C4 = (function (_super) {
+ __extends(C4, _super);
+ function C4() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C4;
+}(Constructor()));
+var C5 = (function (_super) {
+ __extends(C5, _super);
+ function C5() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ return C5;
+}(Constructor()));
diff --git a/tests/baselines/reference/intersectionThisTypes.js b/tests/baselines/reference/intersectionThisTypes.js
new file mode 100644
index 00000000000..9c7be09eeb8
--- /dev/null
+++ b/tests/baselines/reference/intersectionThisTypes.js
@@ -0,0 +1,57 @@
+//// [intersectionThisTypes.ts]
+interface Thing1 {
+ a: number;
+ self(): this;
+}
+
+interface Thing2 {
+ b: number;
+ me(): this;
+}
+
+type Thing3 = Thing1 & Thing2;
+type Thing4 = Thing3 & string[];
+
+function f1(t: Thing3) {
+ t = t.self();
+ t = t.me().self().me();
+}
+
+interface Thing5 extends Thing4 {
+ c: string;
+}
+
+function f2(t: Thing5) {
+ t = t.self();
+ t = t.me().self().me();
+}
+
+interface Component {
+ extend(props: T): this & T;
+}
+
+interface Label extends Component {
+ title: string;
+}
+
+function test(label: Label) {
+ const extended = label.extend({ id: 67 }).extend({ tag: "hello" });
+ extended.id; // Ok
+ extended.tag; // Ok
+}
+
+
+//// [intersectionThisTypes.js]
+function f1(t) {
+ t = t.self();
+ t = t.me().self().me();
+}
+function f2(t) {
+ t = t.self();
+ t = t.me().self().me();
+}
+function test(label) {
+ var extended = label.extend({ id: 67 }).extend({ tag: "hello" });
+ extended.id; // Ok
+ extended.tag; // Ok
+}
diff --git a/tests/baselines/reference/intersectionThisTypes.symbols b/tests/baselines/reference/intersectionThisTypes.symbols
new file mode 100644
index 00000000000..8a8a6cd5496
--- /dev/null
+++ b/tests/baselines/reference/intersectionThisTypes.symbols
@@ -0,0 +1,127 @@
+=== tests/cases/conformance/types/intersection/intersectionThisTypes.ts ===
+interface Thing1 {
+>Thing1 : Symbol(Thing1, Decl(intersectionThisTypes.ts, 0, 0))
+
+ a: number;
+>a : Symbol(Thing1.a, Decl(intersectionThisTypes.ts, 0, 18))
+
+ self(): this;
+>self : Symbol(Thing1.self, Decl(intersectionThisTypes.ts, 1, 14))
+}
+
+interface Thing2 {
+>Thing2 : Symbol(Thing2, Decl(intersectionThisTypes.ts, 3, 1))
+
+ b: number;
+>b : Symbol(Thing2.b, Decl(intersectionThisTypes.ts, 5, 18))
+
+ me(): this;
+>me : Symbol(Thing2.me, Decl(intersectionThisTypes.ts, 6, 14))
+}
+
+type Thing3 = Thing1 & Thing2;
+>Thing3 : Symbol(Thing3, Decl(intersectionThisTypes.ts, 8, 1))
+>Thing1 : Symbol(Thing1, Decl(intersectionThisTypes.ts, 0, 0))
+>Thing2 : Symbol(Thing2, Decl(intersectionThisTypes.ts, 3, 1))
+
+type Thing4 = Thing3 & string[];
+>Thing4 : Symbol(Thing4, Decl(intersectionThisTypes.ts, 10, 30))
+>Thing3 : Symbol(Thing3, Decl(intersectionThisTypes.ts, 8, 1))
+
+function f1(t: Thing3) {
+>f1 : Symbol(f1, Decl(intersectionThisTypes.ts, 11, 32))
+>t : Symbol(t, Decl(intersectionThisTypes.ts, 13, 12))
+>Thing3 : Symbol(Thing3, Decl(intersectionThisTypes.ts, 8, 1))
+
+ t = t.self();
+>t : Symbol(t, Decl(intersectionThisTypes.ts, 13, 12))
+>t.self : Symbol(Thing1.self, Decl(intersectionThisTypes.ts, 1, 14))
+>t : Symbol(t, Decl(intersectionThisTypes.ts, 13, 12))
+>self : Symbol(Thing1.self, Decl(intersectionThisTypes.ts, 1, 14))
+
+ t = t.me().self().me();
+>t : Symbol(t, Decl(intersectionThisTypes.ts, 13, 12))
+>t.me().self().me : Symbol(Thing2.me, Decl(intersectionThisTypes.ts, 6, 14))
+>t.me().self : Symbol(Thing1.self, Decl(intersectionThisTypes.ts, 1, 14))
+>t.me : Symbol(Thing2.me, Decl(intersectionThisTypes.ts, 6, 14))
+>t : Symbol(t, Decl(intersectionThisTypes.ts, 13, 12))
+>me : Symbol(Thing2.me, Decl(intersectionThisTypes.ts, 6, 14))
+>self : Symbol(Thing1.self, Decl(intersectionThisTypes.ts, 1, 14))
+>me : Symbol(Thing2.me, Decl(intersectionThisTypes.ts, 6, 14))
+}
+
+interface Thing5 extends Thing4 {
+>Thing5 : Symbol(Thing5, Decl(intersectionThisTypes.ts, 16, 1))
+>Thing4 : Symbol(Thing4, Decl(intersectionThisTypes.ts, 10, 30))
+
+ c: string;
+>c : Symbol(Thing5.c, Decl(intersectionThisTypes.ts, 18, 33))
+}
+
+function f2(t: Thing5) {
+>f2 : Symbol(f2, Decl(intersectionThisTypes.ts, 20, 1))
+>t : Symbol(t, Decl(intersectionThisTypes.ts, 22, 12))
+>Thing5 : Symbol(Thing5, Decl(intersectionThisTypes.ts, 16, 1))
+
+ t = t.self();
+>t : Symbol(t, Decl(intersectionThisTypes.ts, 22, 12))
+>t.self : Symbol(Thing1.self, Decl(intersectionThisTypes.ts, 1, 14))
+>t : Symbol(t, Decl(intersectionThisTypes.ts, 22, 12))
+>self : Symbol(Thing1.self, Decl(intersectionThisTypes.ts, 1, 14))
+
+ t = t.me().self().me();
+>t : Symbol(t, Decl(intersectionThisTypes.ts, 22, 12))
+>t.me().self().me : Symbol(Thing2.me, Decl(intersectionThisTypes.ts, 6, 14))
+>t.me().self : Symbol(Thing1.self, Decl(intersectionThisTypes.ts, 1, 14))
+>t.me : Symbol(Thing2.me, Decl(intersectionThisTypes.ts, 6, 14))
+>t : Symbol(t, Decl(intersectionThisTypes.ts, 22, 12))
+>me : Symbol(Thing2.me, Decl(intersectionThisTypes.ts, 6, 14))
+>self : Symbol(Thing1.self, Decl(intersectionThisTypes.ts, 1, 14))
+>me : Symbol(Thing2.me, Decl(intersectionThisTypes.ts, 6, 14))
+}
+
+interface Component {
+>Component : Symbol(Component, Decl(intersectionThisTypes.ts, 25, 1))
+
+ extend(props: T): this & T;
+>extend : Symbol(Component.extend, Decl(intersectionThisTypes.ts, 27, 21))
+>T : Symbol(T, Decl(intersectionThisTypes.ts, 28, 11))
+>props : Symbol(props, Decl(intersectionThisTypes.ts, 28, 14))
+>T : Symbol(T, Decl(intersectionThisTypes.ts, 28, 11))
+>T : Symbol(T, Decl(intersectionThisTypes.ts, 28, 11))
+}
+
+interface Label extends Component {
+>Label : Symbol(Label, Decl(intersectionThisTypes.ts, 29, 1))
+>Component : Symbol(Component, Decl(intersectionThisTypes.ts, 25, 1))
+
+ title: string;
+>title : Symbol(Label.title, Decl(intersectionThisTypes.ts, 31, 35))
+}
+
+function test(label: Label) {
+>test : Symbol(test, Decl(intersectionThisTypes.ts, 33, 1))
+>label : Symbol(label, Decl(intersectionThisTypes.ts, 35, 14))
+>Label : Symbol(Label, Decl(intersectionThisTypes.ts, 29, 1))
+
+ const extended = label.extend({ id: 67 }).extend({ tag: "hello" });
+>extended : Symbol(extended, Decl(intersectionThisTypes.ts, 36, 9))
+>label.extend({ id: 67 }).extend : Symbol(Component.extend, Decl(intersectionThisTypes.ts, 27, 21))
+>label.extend : Symbol(Component.extend, Decl(intersectionThisTypes.ts, 27, 21))
+>label : Symbol(label, Decl(intersectionThisTypes.ts, 35, 14))
+>extend : Symbol(Component.extend, Decl(intersectionThisTypes.ts, 27, 21))
+>id : Symbol(id, Decl(intersectionThisTypes.ts, 36, 35))
+>extend : Symbol(Component.extend, Decl(intersectionThisTypes.ts, 27, 21))
+>tag : Symbol(tag, Decl(intersectionThisTypes.ts, 36, 54))
+
+ extended.id; // Ok
+>extended.id : Symbol(id, Decl(intersectionThisTypes.ts, 36, 35))
+>extended : Symbol(extended, Decl(intersectionThisTypes.ts, 36, 9))
+>id : Symbol(id, Decl(intersectionThisTypes.ts, 36, 35))
+
+ extended.tag; // Ok
+>extended.tag : Symbol(tag, Decl(intersectionThisTypes.ts, 36, 54))
+>extended : Symbol(extended, Decl(intersectionThisTypes.ts, 36, 9))
+>tag : Symbol(tag, Decl(intersectionThisTypes.ts, 36, 54))
+}
+
diff --git a/tests/baselines/reference/intersectionThisTypes.types b/tests/baselines/reference/intersectionThisTypes.types
new file mode 100644
index 00000000000..285609cdfdc
--- /dev/null
+++ b/tests/baselines/reference/intersectionThisTypes.types
@@ -0,0 +1,145 @@
+=== tests/cases/conformance/types/intersection/intersectionThisTypes.ts ===
+interface Thing1 {
+>Thing1 : Thing1
+
+ a: number;
+>a : number
+
+ self(): this;
+>self : () => this
+}
+
+interface Thing2 {
+>Thing2 : Thing2
+
+ b: number;
+>b : number
+
+ me(): this;
+>me : () => this
+}
+
+type Thing3 = Thing1 & Thing2;
+>Thing3 : Thing3
+>Thing1 : Thing1
+>Thing2 : Thing2
+
+type Thing4 = Thing3 & string[];
+>Thing4 : Thing4
+>Thing3 : Thing3
+
+function f1(t: Thing3) {
+>f1 : (t: Thing3) => void
+>t : Thing3
+>Thing3 : Thing3
+
+ t = t.self();
+>t = t.self() : Thing3
+>t : Thing3
+>t.self() : Thing3
+>t.self : () => Thing3
+>t : Thing3
+>self : () => Thing3
+
+ t = t.me().self().me();
+>t = t.me().self().me() : Thing3
+>t : Thing3
+>t.me().self().me() : Thing3
+>t.me().self().me : () => Thing3
+>t.me().self() : Thing3
+>t.me().self : () => Thing3
+>t.me() : Thing3
+>t.me : () => Thing3
+>t : Thing3
+>me : () => Thing3
+>self : () => Thing3
+>me : () => Thing3
+}
+
+interface Thing5 extends Thing4 {
+>Thing5 : Thing5
+>Thing4 : Thing4
+
+ c: string;
+>c : string
+}
+
+function f2(t: Thing5) {
+>f2 : (t: Thing5) => void
+>t : Thing5
+>Thing5 : Thing5
+
+ t = t.self();
+>t = t.self() : Thing5
+>t : Thing5
+>t.self() : Thing5
+>t.self : () => Thing5
+>t : Thing5
+>self : () => Thing5
+
+ t = t.me().self().me();
+>t = t.me().self().me() : Thing5
+>t : Thing5
+>t.me().self().me() : Thing5
+>t.me().self().me : () => Thing5
+>t.me().self() : Thing5
+>t.me().self : () => Thing5
+>t.me() : Thing5
+>t.me : () => Thing5
+>t : Thing5
+>me : () => Thing5
+>self : () => Thing5
+>me : () => Thing5
+}
+
+interface Component {
+>Component : Component
+
+ extend(props: T): this & T;
+>extend : (props: T) => this & T
+>T : T
+>props : T
+>T : T
+>T : T
+}
+
+interface Label extends Component {
+>Label : Label
+>Component : Component
+
+ title: string;
+>title : string
+}
+
+function test(label: Label) {
+>test : (label: Label) => void
+>label : Label
+>Label : Label
+
+ const extended = label.extend({ id: 67 }).extend({ tag: "hello" });
+>extended : Label & { id: number; } & { tag: string; }
+>label.extend({ id: 67 }).extend({ tag: "hello" }) : Label & { id: number; } & { tag: string; }
+>label.extend({ id: 67 }).extend : (props: T) => Label & { id: number; } & T
+>label.extend({ id: 67 }) : Label & { id: number; }
+>label.extend : (props: T) => Label & T
+>label : Label
+>extend : (props: T) => Label & T
+>{ id: 67 } : { id: number; }
+>id : number
+>67 : 67
+>extend : (props: T) => Label & { id: number; } & T
+>{ tag: "hello" } : { tag: string; }
+>tag : string
+>"hello" : "hello"
+
+ extended.id; // Ok
+>extended.id : number
+>extended : Label & { id: number; } & { tag: string; }
+>id : number
+
+ extended.tag; // Ok
+>extended.tag : string
+>extended : Label & { id: number; } & { tag: string; }
+>tag : string
+}
+
diff --git a/tests/baselines/reference/keyofAndIndexedAccess.js b/tests/baselines/reference/keyofAndIndexedAccess.js
index a86184c8ff0..e7df8bbd5a1 100644
--- a/tests/baselines/reference/keyofAndIndexedAccess.js
+++ b/tests/baselines/reference/keyofAndIndexedAccess.js
@@ -504,6 +504,18 @@ function updateIds2(
// Repro from #13514
declare function head>(list: T): T[0];
+
+// Repro from #13604
+
+class A {
+ props: T & { foo: string };
+}
+
+class B extends A<{ x: number}> {
+ f(p: this["props"]) {
+ p.x;
+ }
+}
//// [keyofAndIndexedAccess.js]
@@ -834,6 +846,22 @@ function updateIds2(obj, key, stringMap) {
var x = obj[key];
stringMap[x]; // Should be OK.
}
+// Repro from #13604
+var A = (function () {
+ function A() {
+ }
+ return A;
+}());
+var B = (function (_super) {
+ __extends(B, _super);
+ function B() {
+ return _super !== null && _super.apply(this, arguments) || this;
+ }
+ B.prototype.f = function (p) {
+ p.x;
+ };
+ return B;
+}(A));
//// [keyofAndIndexedAccess.d.ts]
@@ -1066,3 +1094,13 @@ declare function updateIds2>(list: T): T[0];
+declare class A {
+ props: T & {
+ foo: string;
+ };
+}
+declare class B extends A<{
+ x: number;
+}> {
+ f(p: this["props"]): void;
+}
diff --git a/tests/baselines/reference/keyofAndIndexedAccess.symbols b/tests/baselines/reference/keyofAndIndexedAccess.symbols
index 4c12c6554c9..01501cd719c 100644
--- a/tests/baselines/reference/keyofAndIndexedAccess.symbols
+++ b/tests/baselines/reference/keyofAndIndexedAccess.symbols
@@ -1816,3 +1816,31 @@ declare function head>(list: T): T[0];
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 504, 22))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 504, 22))
+// Repro from #13604
+
+class A {
+>A : Symbol(A, Decl(keyofAndIndexedAccess.ts, 504, 59))
+>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 508, 8))
+
+ props: T & { foo: string };
+>props : Symbol(A.props, Decl(keyofAndIndexedAccess.ts, 508, 12))
+>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 508, 8))
+>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 509, 13))
+}
+
+class B extends A<{ x: number}> {
+>B : Symbol(B, Decl(keyofAndIndexedAccess.ts, 510, 1))
+>A : Symbol(A, Decl(keyofAndIndexedAccess.ts, 504, 59))
+>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 512, 19))
+
+ f(p: this["props"]) {
+>f : Symbol(B.f, Decl(keyofAndIndexedAccess.ts, 512, 33))
+>p : Symbol(p, Decl(keyofAndIndexedAccess.ts, 513, 3))
+
+ p.x;
+>p.x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 512, 19))
+>p : Symbol(p, Decl(keyofAndIndexedAccess.ts, 513, 3))
+>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 512, 19))
+ }
+}
+
diff --git a/tests/baselines/reference/keyofAndIndexedAccess.types b/tests/baselines/reference/keyofAndIndexedAccess.types
index 3919d768151..21c9d645ce4 100644
--- a/tests/baselines/reference/keyofAndIndexedAccess.types
+++ b/tests/baselines/reference/keyofAndIndexedAccess.types
@@ -2138,3 +2138,31 @@ declare function head>(list: T): T[0];
>T : T
>T : T
+// Repro from #13604
+
+class A {
+>A : A
+>T : T
+
+ props: T & { foo: string };
+>props : T & { foo: string; }
+>T : T
+>foo : string
+}
+
+class B extends A<{ x: number}> {
+>B : B
+>A : A<{ x: number; }>
+>x : number
+
+ f(p: this["props"]) {
+>f : (p: this["props"]) => void
+>p : this["props"]
+
+ p.x;
+>p.x : number
+>p : this["props"]
+>x : number
+ }
+}
+
diff --git a/tests/baselines/reference/mappedTypes1.js b/tests/baselines/reference/mappedTypes1.js
index 1998ad5ab6b..4dd8f172179 100644
--- a/tests/baselines/reference/mappedTypes1.js
+++ b/tests/baselines/reference/mappedTypes1.js
@@ -139,9 +139,9 @@ declare let x2: string;
declare let x3: number;
declare let x4: {
toString: void;
- valueOf: void;
toFixed: void;
toExponential: void;
toPrecision: void;
+ valueOf: void;
toLocaleString: void;
};
diff --git a/tests/baselines/reference/mappedTypes1.types b/tests/baselines/reference/mappedTypes1.types
index 35d13143bab..a9a7f53a899 100644
--- a/tests/baselines/reference/mappedTypes1.types
+++ b/tests/baselines/reference/mappedTypes1.types
@@ -165,7 +165,7 @@ let x3 = f3();
>f3 : () => { [P in keyof T1]: void; }
let x4 = f4();
->x4 : { toString: void; valueOf: void; toFixed: void; toExponential: void; toPrecision: void; toLocaleString: void; }
->f4() : { toString: void; valueOf: void; toFixed: void; toExponential: void; toPrecision: void; toLocaleString: void; }
+>x4 : { toString: void; toFixed: void; toExponential: void; toPrecision: void; valueOf: void; toLocaleString: void; }
+>f4() : { toString: void; toFixed: void; toExponential: void; toPrecision: void; valueOf: void; toLocaleString: void; }
>f4 : () => { [P in keyof T1]: void; }
diff --git a/tests/baselines/reference/mergedDeclarations7.errors.txt b/tests/baselines/reference/mergedDeclarations7.errors.txt
new file mode 100644
index 00000000000..cd9b3a5e939
--- /dev/null
+++ b/tests/baselines/reference/mergedDeclarations7.errors.txt
@@ -0,0 +1,32 @@
+tests/cases/compiler/test.ts(4,5): error TS2322: Type 'PassportStatic' is not assignable to type 'Passport'.
+ Types of property 'use' are incompatible.
+ Type '() => PassportStatic' is not assignable to type '() => this'.
+ Type 'PassportStatic' is not assignable to type 'this'.
+
+
+==== tests/cases/compiler/passport.d.ts (0 errors) ====
+ declare module 'passport' {
+ namespace passport {
+ interface Passport {
+ use(): this;
+ }
+
+ interface PassportStatic extends Passport {
+ Passport: {new(): Passport};
+ }
+ }
+
+ const passport: passport.PassportStatic;
+ export = passport;
+ }
+
+==== tests/cases/compiler/test.ts (1 errors) ====
+ import * as passport from "passport";
+ import { Passport } from "passport";
+
+ let p: Passport = passport.use();
+ ~
+!!! error TS2322: Type 'PassportStatic' is not assignable to type 'Passport'.
+!!! error TS2322: Types of property 'use' are incompatible.
+!!! error TS2322: Type '() => PassportStatic' is not assignable to type '() => this'.
+!!! error TS2322: Type 'PassportStatic' is not assignable to type 'this'.
\ No newline at end of file
diff --git a/tests/baselines/reference/mergedDeclarations7.js b/tests/baselines/reference/mergedDeclarations7.js
new file mode 100644
index 00000000000..e3d1ddc6e0e
--- /dev/null
+++ b/tests/baselines/reference/mergedDeclarations7.js
@@ -0,0 +1,28 @@
+//// [tests/cases/compiler/mergedDeclarations7.ts] ////
+
+//// [passport.d.ts]
+declare module 'passport' {
+ namespace passport {
+ interface Passport {
+ use(): this;
+ }
+
+ interface PassportStatic extends Passport {
+ Passport: {new(): Passport};
+ }
+ }
+
+ const passport: passport.PassportStatic;
+ export = passport;
+}
+
+//// [test.ts]
+import * as passport from "passport";
+import { Passport } from "passport";
+
+let p: Passport = passport.use();
+
+//// [test.js]
+"use strict";
+var passport = require("passport");
+var p = passport.use();
diff --git a/tests/baselines/reference/metadataOfEventAlias.js b/tests/baselines/reference/metadataOfEventAlias.js
new file mode 100644
index 00000000000..8a22a90bc2e
--- /dev/null
+++ b/tests/baselines/reference/metadataOfEventAlias.js
@@ -0,0 +1,38 @@
+//// [tests/cases/compiler/metadataOfEventAlias.ts] ////
+
+//// [event.ts]
+
+export interface Event { title: string };
+
+//// [test.ts]
+import { Event } from './event';
+function Input(target: any, key: string): void { }
+export class SomeClass {
+ @Input event: Event;
+}
+
+//// [event.js]
+"use strict";
+;
+//// [test.js]
+"use strict";
+var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
+};
+var __metadata = (this && this.__metadata) || function (k, v) {
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
+};
+function Input(target, key) { }
+var SomeClass = (function () {
+ function SomeClass() {
+ }
+ return SomeClass;
+}());
+__decorate([
+ Input,
+ __metadata("design:type", Object)
+], SomeClass.prototype, "event", void 0);
+exports.SomeClass = SomeClass;
diff --git a/tests/baselines/reference/metadataOfEventAlias.symbols b/tests/baselines/reference/metadataOfEventAlias.symbols
new file mode 100644
index 00000000000..441714e63e6
--- /dev/null
+++ b/tests/baselines/reference/metadataOfEventAlias.symbols
@@ -0,0 +1,23 @@
+=== tests/cases/compiler/event.ts ===
+
+export interface Event { title: string };
+>Event : Symbol(Event, Decl(event.ts, 0, 0))
+>title : Symbol(Event.title, Decl(event.ts, 1, 24))
+
+=== tests/cases/compiler/test.ts ===
+import { Event } from './event';
+>Event : Symbol(Event, Decl(test.ts, 0, 8))
+
+function Input(target: any, key: string): void { }
+>Input : Symbol(Input, Decl(test.ts, 0, 32))
+>target : Symbol(target, Decl(test.ts, 1, 15))
+>key : Symbol(key, Decl(test.ts, 1, 27))
+
+export class SomeClass {
+>SomeClass : Symbol(SomeClass, Decl(test.ts, 1, 50))
+
+ @Input event: Event;
+>Input : Symbol(Input, Decl(test.ts, 0, 32))
+>event : Symbol(SomeClass.event, Decl(test.ts, 2, 24))
+>Event : Symbol(Event, Decl(test.ts, 0, 8))
+}
diff --git a/tests/baselines/reference/metadataOfEventAlias.types b/tests/baselines/reference/metadataOfEventAlias.types
new file mode 100644
index 00000000000..b644552f9c2
--- /dev/null
+++ b/tests/baselines/reference/metadataOfEventAlias.types
@@ -0,0 +1,23 @@
+=== tests/cases/compiler/event.ts ===
+
+export interface Event { title: string };
+>Event : Event
+>title : string
+
+=== tests/cases/compiler/test.ts ===
+import { Event } from './event';
+>Event : any
+
+function Input(target: any, key: string): void { }
+>Input : (target: any, key: string) => void
+>target : any
+>key : string
+
+export class SomeClass {
+>SomeClass : SomeClass
+
+ @Input event: Event;
+>Input : (target: any, key: string) => void
+>event : Event
+>Event : Event
+}
diff --git a/tests/baselines/reference/noBundledEmitFromNodeModules.js b/tests/baselines/reference/noBundledEmitFromNodeModules.js
new file mode 100644
index 00000000000..67216a408af
--- /dev/null
+++ b/tests/baselines/reference/noBundledEmitFromNodeModules.js
@@ -0,0 +1,20 @@
+//// [tests/cases/compiler/noBundledEmitFromNodeModules.ts] ////
+
+//// [index.ts]
+
+export class C {}
+
+//// [a.ts]
+import { C } from "projB";
+
+
+//// [out.js]
+System.register("a", [], function (exports_1, context_1) {
+ "use strict";
+ var __moduleName = context_1 && context_1.id;
+ return {
+ setters: [],
+ execute: function () {
+ }
+ };
+});
diff --git a/tests/baselines/reference/noBundledEmitFromNodeModules.symbols b/tests/baselines/reference/noBundledEmitFromNodeModules.symbols
new file mode 100644
index 00000000000..a1f6c67e4b4
--- /dev/null
+++ b/tests/baselines/reference/noBundledEmitFromNodeModules.symbols
@@ -0,0 +1,9 @@
+=== /a.ts ===
+import { C } from "projB";
+>C : Symbol(C, Decl(a.ts, 0, 8))
+
+=== /node_modules/projB/index.ts ===
+
+export class C {}
+>C : Symbol(C, Decl(index.ts, 0, 0))
+
diff --git a/tests/baselines/reference/noBundledEmitFromNodeModules.types b/tests/baselines/reference/noBundledEmitFromNodeModules.types
new file mode 100644
index 00000000000..a11bad24aaf
--- /dev/null
+++ b/tests/baselines/reference/noBundledEmitFromNodeModules.types
@@ -0,0 +1,9 @@
+=== /a.ts ===
+import { C } from "projB";
+>C : typeof C
+
+=== /node_modules/projB/index.ts ===
+
+export class C {}
+>C : C
+
diff --git a/tests/baselines/reference/nonPrimitiveAccessProperty.errors.txt b/tests/baselines/reference/nonPrimitiveAccessProperty.errors.txt
index 8ef94c64448..0a6dfa66b86 100644
--- a/tests/baselines/reference/nonPrimitiveAccessProperty.errors.txt
+++ b/tests/baselines/reference/nonPrimitiveAccessProperty.errors.txt
@@ -1,10 +1,16 @@
tests/cases/conformance/types/nonPrimitive/nonPrimitiveAccessProperty.ts(3,3): error TS2339: Property 'nonExist' does not exist on type 'object'.
+tests/cases/conformance/types/nonPrimitive/nonPrimitiveAccessProperty.ts(5,7): error TS2459: Type 'object' has no property 'destructuring' and no string index signature.
-==== tests/cases/conformance/types/nonPrimitive/nonPrimitiveAccessProperty.ts (1 errors) ====
+==== tests/cases/conformance/types/nonPrimitive/nonPrimitiveAccessProperty.ts (2 errors) ====
var a: object;
a.toString();
a.nonExist(); // error
~~~~~~~~
!!! error TS2339: Property 'nonExist' does not exist on type 'object'.
+
+ var { destructuring } = a; // error
+ ~~~~~~~~~~~~~
+!!! error TS2459: Type 'object' has no property 'destructuring' and no string index signature.
+ var { ...rest } = a; // ok
\ No newline at end of file
diff --git a/tests/baselines/reference/nonPrimitiveAccessProperty.js b/tests/baselines/reference/nonPrimitiveAccessProperty.js
index a71b2aba865..abfe2605e32 100644
--- a/tests/baselines/reference/nonPrimitiveAccessProperty.js
+++ b/tests/baselines/reference/nonPrimitiveAccessProperty.js
@@ -2,9 +2,23 @@
var a: object;
a.toString();
a.nonExist(); // error
+
+var { destructuring } = a; // error
+var { ...rest } = a; // ok
//// [nonPrimitiveAccessProperty.js]
+var __rest = (this && this.__rest) || function (s, e) {
+ var t = {};
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
+ t[p] = s[p];
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
+ t[p[i]] = s[p[i]];
+ return t;
+};
var a;
a.toString();
a.nonExist(); // error
+var destructuring = a.destructuring; // error
+var rest = __rest(a, []); // ok
diff --git a/tests/baselines/reference/objectSpread.js b/tests/baselines/reference/objectSpread.js
index 4305e17ab31..2bc3b9e11bd 100644
--- a/tests/baselines/reference/objectSpread.js
+++ b/tests/baselines/reference/objectSpread.js
@@ -78,7 +78,8 @@ let computedAfter: { a: number, b: string, "at the end": number } =
// shortcut syntax
let a = 12;
let shortCutted: { a: number, b: string } = { ...o, a }
-
+// non primitive
+let spreadNonPrimitive = { ...