Merge pull request #19513 from Microsoft/strictObjectLiterals

Improved type inference for object literals
This commit is contained in:
Anders Hejlsberg 2017-10-28 17:13:21 -07:00 committed by GitHub
commit 7798f69558
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 1199 additions and 141 deletions

View file

@ -260,6 +260,7 @@ namespace ts {
const literalTypes = createMap<LiteralType>();
const indexedAccessTypes = createMap<IndexedAccessType>();
const evolvingArrayTypes: EvolvingArrayType[] = [];
const undefinedProperties = createMap<Symbol>() as UnderscoreEscapedMap<Symbol>;
const unknownSymbol = createSymbol(SymbolFlags.Property, "unknown" as __String);
const resolvingSymbol = createSymbol(0, InternalSymbolName.Resolving);
@ -7984,7 +7985,7 @@ namespace ts {
const spread = createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
spread.flags |= propagatedFlags;
spread.flags |= TypeFlags.FreshLiteral | TypeFlags.ContainsObjectLiteral;
(spread as ObjectType).objectFlags |= ObjectFlags.ObjectLiteral;
(spread as ObjectType).objectFlags |= (ObjectFlags.ObjectLiteral | ObjectFlags.ContainsSpread);
spread.symbol = symbol;
return spread;
}
@ -9026,7 +9027,7 @@ namespace ts {
if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;
if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && source.flags & TypeFlags.FreshLiteral) {
if (isObjectLiteralType(source) && source.flags & TypeFlags.FreshLiteral) {
if (hasExcessProperties(<FreshObjectLiteralType>source, target, reportErrors)) {
if (reportErrors) {
reportRelationError(headMessage, source, target);
@ -9596,7 +9597,7 @@ namespace ts {
if (relation === identityRelation) {
return propertiesIdenticalTo(source, target);
}
const requireOptionalProperties = relation === subtypeRelation && !(getObjectFlags(source) & ObjectFlags.ObjectLiteral);
const requireOptionalProperties = relation === subtypeRelation && !isObjectLiteralType(source);
const unmatchedProperty = getUnmatchedProperty(source, target, requireOptionalProperties);
if (unmatchedProperty) {
if (reportErrors) {
@ -9604,6 +9605,19 @@ namespace ts {
}
return Ternary.False;
}
if (isObjectLiteralType(target)) {
for (const sourceProp of getPropertiesOfType(source)) {
if (!getPropertyOfObjectType(target, sourceProp.escapedName)) {
const sourceType = getTypeOfSymbol(sourceProp);
if (!(sourceType === undefinedType || sourceType === undefinedWideningType)) {
if (reportErrors) {
reportError(Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(sourceProp), typeToString(target));
}
return Ternary.False;
}
}
}
}
let result = Ternary.True;
const properties = getPropertiesOfObjectType(target);
for (const targetProp of properties) {
@ -10425,7 +10439,7 @@ namespace ts {
* Leave signatures alone since they are not subject to the check.
*/
function getRegularTypeOfObjectLiteral(type: Type): Type {
if (!(getObjectFlags(type) & ObjectFlags.ObjectLiteral && type.flags & TypeFlags.FreshLiteral)) {
if (!(isObjectLiteralType(type) && type.flags & TypeFlags.FreshLiteral)) {
return type;
}
const regularType = (<FreshObjectLiteralType>type).regularType;
@ -10447,18 +10461,74 @@ namespace ts {
return regularNew;
}
function getWidenedProperty(prop: Symbol): Symbol {
function createWideningContext(parent: WideningContext, propertyName: __String, siblings: Type[]): WideningContext {
return { parent, propertyName, siblings, resolvedPropertyNames: undefined };
}
function getSiblingsOfContext(context: WideningContext): Type[] {
if (!context.siblings) {
const siblings: Type[] = [];
for (const type of getSiblingsOfContext(context.parent)) {
if (isObjectLiteralType(type)) {
const prop = getPropertyOfObjectType(type, context.propertyName);
if (prop) {
forEachType(getTypeOfSymbol(prop), t => {
siblings.push(t);
});
}
}
}
context.siblings = siblings;
}
return context.siblings;
}
function getPropertyNamesOfContext(context: WideningContext): __String[] {
if (!context.resolvedPropertyNames) {
const names = createMap<boolean>() as UnderscoreEscapedMap<boolean>;
for (const t of getSiblingsOfContext(context)) {
if (isObjectLiteralType(t) && !(getObjectFlags(t) & ObjectFlags.ContainsSpread)) {
for (const prop of getPropertiesOfType(t)) {
names.set(prop.escapedName, true);
}
}
}
context.resolvedPropertyNames = arrayFrom(names.keys());
}
return context.resolvedPropertyNames;
}
function getWidenedProperty(prop: Symbol, context: WideningContext): Symbol {
const original = getTypeOfSymbol(prop);
const widened = getWidenedType(original);
const propContext = context && createWideningContext(context, prop.escapedName, /*siblings*/ undefined);
const widened = getWidenedTypeWithContext(original, propContext);
return widened === original ? prop : createSymbolWithType(prop, widened);
}
function getWidenedTypeOfObjectLiteral(type: Type): Type {
function getUndefinedProperty(name: __String) {
const cached = undefinedProperties.get(name);
if (cached) {
return cached;
}
const result = createSymbol(SymbolFlags.Property | SymbolFlags.Optional, name);
result.type = undefinedType;
undefinedProperties.set(name, result);
return result;
}
function getWidenedTypeOfObjectLiteral(type: Type, context: WideningContext): Type {
const members = createSymbolTable();
for (const prop of getPropertiesOfObjectType(type)) {
// Since get accessors already widen their return value there is no need to
// widen accessor based properties here.
members.set(prop.escapedName, prop.flags & SymbolFlags.Property ? getWidenedProperty(prop) : prop);
members.set(prop.escapedName, prop.flags & SymbolFlags.Property ? getWidenedProperty(prop, context) : prop);
}
if (context) {
for (const name of getPropertyNamesOfContext(context)) {
if (!members.has(name)) {
members.set(name, getUndefinedProperty(name));
}
}
}
const stringIndexInfo = getIndexInfoOfType(type, IndexKind.String);
const numberIndexInfo = getIndexInfoOfType(type, IndexKind.Number);
@ -10467,20 +10537,25 @@ namespace ts {
numberIndexInfo && createIndexInfo(getWidenedType(numberIndexInfo.type), numberIndexInfo.isReadonly));
}
function getWidenedConstituentType(type: Type): Type {
return type.flags & TypeFlags.Nullable ? type : getWidenedType(type);
function getWidenedType(type: Type) {
return getWidenedTypeWithContext(type, /*context*/ undefined);
}
function getWidenedType(type: Type): Type {
function getWidenedTypeWithContext(type: Type, context: WideningContext): Type {
if (type.flags & TypeFlags.RequiresWidening) {
if (type.flags & TypeFlags.Nullable) {
return anyType;
}
if (getObjectFlags(type) & ObjectFlags.ObjectLiteral) {
return getWidenedTypeOfObjectLiteral(type);
if (isObjectLiteralType(type)) {
return getWidenedTypeOfObjectLiteral(type, context);
}
if (type.flags & TypeFlags.Union) {
return getUnionType(sameMap((<UnionType>type).types, getWidenedConstituentType));
const unionContext = context || createWideningContext(/*parent*/ undefined, /*propertyName*/ undefined, (<UnionType>type).types);
const widenedTypes = sameMap((<UnionType>type).types, t => t.flags & TypeFlags.Nullable ? t : getWidenedTypeWithContext(t, unionContext));
// Widening an empty object literal transitions from a highly restrictive type to
// a highly inclusive one. For that reason we perform subtype reduction here if the
// union includes empty object types (e.g. reducing {} | string to just {}).
return getUnionType(widenedTypes, some(widenedTypes, isEmptyObjectType));
}
if (isArrayType(type) || isTupleType(type)) {
return createTypeReference((<TypeReference>type).target, sameMap((<TypeReference>type).typeArguments, getWidenedType));
@ -10502,28 +10577,35 @@ namespace ts {
*/
function reportWideningErrorsInType(type: Type): boolean {
let errorReported = false;
if (type.flags & TypeFlags.Union) {
for (const t of (<UnionType>type).types) {
if (reportWideningErrorsInType(t)) {
if (type.flags & TypeFlags.ContainsWideningType) {
if (type.flags & TypeFlags.Union) {
if (some((<UnionType>type).types, isEmptyObjectType)) {
errorReported = true;
}
}
}
if (isArrayType(type) || isTupleType(type)) {
for (const t of (<TypeReference>type).typeArguments) {
if (reportWideningErrorsInType(t)) {
errorReported = true;
}
}
}
if (getObjectFlags(type) & ObjectFlags.ObjectLiteral) {
for (const p of getPropertiesOfObjectType(type)) {
const t = getTypeOfSymbol(p);
if (t.flags & TypeFlags.ContainsWideningType) {
if (!reportWideningErrorsInType(t)) {
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolName(p), typeToString(getWidenedType(t)));
else {
for (const t of (<UnionType>type).types) {
if (reportWideningErrorsInType(t)) {
errorReported = true;
}
}
}
}
if (isArrayType(type) || isTupleType(type)) {
for (const t of (<TypeReference>type).typeArguments) {
if (reportWideningErrorsInType(t)) {
errorReported = true;
}
}
}
if (isObjectLiteralType(type)) {
for (const p of getPropertiesOfObjectType(type)) {
const t = getTypeOfSymbol(p);
if (t.flags & TypeFlags.ContainsWideningType) {
if (!reportWideningErrorsInType(t)) {
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolName(p), typeToString(getWidenedType(t)));
}
errorReported = true;
}
errorReported = true;
}
}
}
@ -11029,11 +11111,28 @@ namespace ts {
return constraint && maybeTypeOfKind(constraint, TypeFlags.Primitive | TypeFlags.Index);
}
function isObjectLiteralType(type: Type) {
return !!(getObjectFlags(type) & ObjectFlags.ObjectLiteral);
}
function widenObjectLiteralCandidates(candidates: Type[]): Type[] {
if (candidates.length > 1) {
const objectLiterals = filter(candidates, isObjectLiteralType);
if (objectLiterals.length) {
const objectLiteralsType = getWidenedType(getUnionType(objectLiterals, /*subtypeReduction*/ true));
return concatenate(filter(candidates, t => !isObjectLiteralType(t)), [objectLiteralsType]);
}
}
return candidates;
}
function getInferredType(context: InferenceContext, index: number): Type {
const inference = context.inferences[index];
let inferredType = inference.inferredType;
if (!inferredType) {
if (inference.candidates) {
// Extract all object literal types and replace them with a single widened and normalized type.
const candidates = widenObjectLiteralCandidates(inference.candidates);
// We widen inferred literal types if
// all inferences were made to top-level ocurrences of the type parameter, and
// the type parameter has no constraint or its constraint includes no primitive or literal types, and
@ -11042,7 +11141,7 @@ namespace ts {
const widenLiteralTypes = inference.topLevel &&
!hasPrimitiveConstraint(inference.typeParameter) &&
(inference.isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), inference.typeParameter));
const baseCandidates = widenLiteralTypes ? sameMap(inference.candidates, getWidenedLiteralType) : inference.candidates;
const baseCandidates = widenLiteralTypes ? sameMap(candidates, getWidenedLiteralType) : candidates;
// If all inferences were made from contravariant positions, infer a common subtype. Otherwise, if
// union types were requested or if all inferences were made from the return type position, infer a
// union type. Otherwise, infer a common supertype.

View file

@ -3327,6 +3327,7 @@ namespace ts {
ObjectLiteral = 1 << 7, // Originates in an object literal
EvolvingArray = 1 << 8, // Evolving array type
ObjectLiteralPatternWithComputedProperties = 1 << 9, // Object literal pattern with computed properties
ContainsSpread = 1 << 10, // Object literal contains spread operation
ClassOrInterface = Class | Interface
}
@ -3609,6 +3610,14 @@ namespace ts {
compareTypes: TypeComparer; // Type comparer function
}
/* @internal */
export interface WideningContext {
parent?: WideningContext; // Parent context
propertyName?: __String; // Name of property in parent
siblings?: Type[]; // Types of siblings
resolvedPropertyNames?: __String[]; // Property names occurring in sibling object literals
}
/* @internal */
export const enum SpecialPropertyAssignmentKind {
None,

View file

@ -2040,6 +2040,7 @@ declare namespace ts {
ObjectLiteral = 128,
EvolvingArray = 256,
ObjectLiteralPatternWithComputedProperties = 512,
ContainsSpread = 1024,
ClassOrInterface = 3,
}
interface ObjectType extends Type {

View file

@ -2040,6 +2040,7 @@ declare namespace ts {
ObjectLiteral = 128,
EvolvingArray = 256,
ObjectLiteralPatternWithComputedProperties = 512,
ContainsSpread = 1024,
ClassOrInterface = 3,
}
interface ObjectType extends Type {

View file

@ -4,11 +4,12 @@ tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclarati
tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration10_es2017.ts(1,33): error TS2304: Cannot find name 'await'.
tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration10_es2017.ts(1,38): error TS1005: ';' expected.
tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration10_es2017.ts(1,39): error TS1128: Declaration or statement expected.
tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration10_es2017.ts(1,41): error TS2365: Operator '>' cannot be applied to types 'boolean' and '{}'.
tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration10_es2017.ts(1,49): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration10_es2017.ts(1,53): error TS1109: Expression expected.
==== tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration10_es2017.ts (8 errors) ====
==== tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration10_es2017.ts (9 errors) ====
async function foo(a = await => await): Promise<void> {
~~~~~~~~~
!!! error TS2371: A parameter initializer is only allowed in a function or constructor implementation.
@ -22,8 +23,11 @@ tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclarati
!!! error TS1005: ';' expected.
~
!!! error TS1128: Declaration or statement expected.
~~~~~~~~~~~~~~~
~~~~
!!! error TS2532: Object is possibly 'undefined'.
~
!!! error TS1109: Expression expected.
}
}
~
!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and '{}'.

View file

@ -4,11 +4,12 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts(1,33): error TS2304: Cannot find name 'await'.
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts(1,38): error TS1005: ';' expected.
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts(1,39): error TS1128: Declaration or statement expected.
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts(1,41): error TS2365: Operator '>' cannot be applied to types 'boolean' and '{}'.
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts(1,49): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts(1,53): error TS1109: Expression expected.
==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts (8 errors) ====
==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration10_es5.ts (9 errors) ====
async function foo(a = await => await): Promise<void> {
~~~~~~~~~
!!! error TS2371: A parameter initializer is only allowed in a function or constructor implementation.
@ -22,8 +23,11 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1
!!! error TS1005: ';' expected.
~
!!! error TS1128: Declaration or statement expected.
~~~~~~~~~~~~~~~
~~~~
!!! error TS2532: Object is possibly 'undefined'.
~
!!! error TS1109: Expression expected.
}
}
~
!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and '{}'.

View file

@ -4,11 +4,12 @@ tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration1
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration10_es6.ts(1,33): error TS2304: Cannot find name 'await'.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration10_es6.ts(1,38): error TS1005: ';' expected.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration10_es6.ts(1,39): error TS1128: Declaration or statement expected.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration10_es6.ts(1,41): error TS2365: Operator '>' cannot be applied to types 'boolean' and '{}'.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration10_es6.ts(1,49): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration10_es6.ts(1,53): error TS1109: Expression expected.
==== tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration10_es6.ts (8 errors) ====
==== tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration10_es6.ts (9 errors) ====
async function foo(a = await => await): Promise<void> {
~~~~~~~~~
!!! error TS2371: A parameter initializer is only allowed in a function or constructor implementation.
@ -22,8 +23,11 @@ tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration1
!!! error TS1005: ';' expected.
~
!!! error TS1128: Declaration or statement expected.
~~~~~~~~~~~~~~~
~~~~
!!! error TS2532: Object is possibly 'undefined'.
~
!!! error TS1109: Expression expected.
}
}
~
!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and '{}'.

View file

@ -2,11 +2,12 @@ tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclarati
tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration5_es2017.ts(1,20): error TS2304: Cannot find name 'await'.
tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration5_es2017.ts(1,25): error TS1005: ';' expected.
tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration5_es2017.ts(1,26): error TS1128: Declaration or statement expected.
tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration5_es2017.ts(1,28): error TS2365: Operator '>' cannot be applied to types 'boolean' and '{}'.
tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration5_es2017.ts(1,36): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration5_es2017.ts(1,40): error TS1109: Expression expected.
==== tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration5_es2017.ts (6 errors) ====
==== tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclaration5_es2017.ts (7 errors) ====
async function foo(await): Promise<void> {
~~~~~
!!! error TS1138: Parameter declaration expected.
@ -16,8 +17,11 @@ tests/cases/conformance/async/es2017/functionDeclarations/asyncFunctionDeclarati
!!! error TS1005: ';' expected.
~
!!! error TS1128: Declaration or statement expected.
~~~~~~~~~~~~~~~
~~~~
!!! error TS2532: Object is possibly 'undefined'.
~
!!! error TS1109: Expression expected.
}
}
~
!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and '{}'.

View file

@ -2,11 +2,12 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts(1,20): error TS2304: Cannot find name 'await'.
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts(1,25): error TS1005: ';' expected.
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts(1,26): error TS1128: Declaration or statement expected.
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts(1,28): error TS2365: Operator '>' cannot be applied to types 'boolean' and '{}'.
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts(1,36): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts(1,40): error TS1109: Expression expected.
==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts (6 errors) ====
==== tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5_es5.ts (7 errors) ====
async function foo(await): Promise<void> {
~~~~~
!!! error TS1138: Parameter declaration expected.
@ -16,8 +17,11 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration5
!!! error TS1005: ';' expected.
~
!!! error TS1128: Declaration or statement expected.
~~~~~~~~~~~~~~~
~~~~
!!! error TS2532: Object is possibly 'undefined'.
~
!!! error TS1109: Expression expected.
}
}
~
!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and '{}'.

View file

@ -2,11 +2,12 @@ tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration5
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration5_es6.ts(1,20): error TS2304: Cannot find name 'await'.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration5_es6.ts(1,25): error TS1005: ';' expected.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration5_es6.ts(1,26): error TS1128: Declaration or statement expected.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration5_es6.ts(1,28): error TS2365: Operator '>' cannot be applied to types 'boolean' and '{}'.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration5_es6.ts(1,36): error TS2532: Object is possibly 'undefined'.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration5_es6.ts(1,40): error TS1109: Expression expected.
==== tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration5_es6.ts (6 errors) ====
==== tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration5_es6.ts (7 errors) ====
async function foo(await): Promise<void> {
~~~~~
!!! error TS1138: Parameter declaration expected.
@ -16,8 +17,11 @@ tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration5
!!! error TS1005: ';' expected.
~
!!! error TS1128: Declaration or statement expected.
~~~~~~~~~~~~~~~
~~~~
!!! error TS2532: Object is possibly 'undefined'.
~
!!! error TS1109: Expression expected.
}
}
~
!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and '{}'.

View file

@ -47,7 +47,7 @@ var r = true ? 1 : 2;
var r3 = true ? 1 : {};
>r3 : {}
>true ? 1 : {} : {}
>true ? 1 : {} : 1 | {}
>true : true
>1 : 1
>{} : {}

View file

@ -45,7 +45,7 @@ var result1 = true ? x : a;
//Expr1 and Expr2 are literals
true ? {} : 1;
>true ? {} : 1 : {}
>true ? {} : 1 : 1 | {}
>true : true
>{} : {}
>1 : 1
@ -64,13 +64,13 @@ true ? { a: 1 } : { a: 2, b: 'string' };
var result2 = true ? {} : 1;
>result2 : {}
>true ? {} : 1 : {}
>true ? {} : 1 : 1 | {}
>true : true
>{} : {}
>1 : 1
var result3 = true ? { a: 1 } : { a: 2, b: 'string' };
>result3 : { a: number; } | { a: number; b: string; }
>result3 : { a: number; b?: undefined; } | { a: number; b: string; }
>true ? { a: 1 } : { a: 2, b: 'string' } : { a: number; } | { a: number; b: string; }
>true : true
>{ a: 1 } : { a: number; }
@ -125,7 +125,7 @@ var result5 = true ? a : x;
//Expr1 and Expr2 are literals
true ? 1 : {};
>true ? 1 : {} : {}
>true ? 1 : {} : 1 | {}
>true : true
>1 : 1
>{} : {}
@ -144,13 +144,13 @@ true ? { a: 2, b: 'string' } : { a: 1 };
var result6 = true ? 1 : {};
>result6 : {}
>true ? 1 : {} : {}
>true ? 1 : {} : 1 | {}
>true : true
>1 : 1
>{} : {}
var result7 = true ? { a: 2, b: 'string' } : { a: 1 };
>result7 : { a: number; b: string; } | { a: number; }
>result7 : { a: number; b: string; } | { a: number; b?: undefined; }
>true ? { a: 2, b: 'string' } : { a: 1 } : { a: number; b: string; } | { a: number; }
>true : true
>{ a: 2, b: 'string' } : { a: number; b: string; }

View file

@ -22,13 +22,13 @@ var c = [1, '', null]; // {}[]
var d = [{}, 1]; // {}[]
>d : {}[]
>[{}, 1] : {}[]
>[{}, 1] : (number | {})[]
>{} : {}
>1 : 1
var e = [{}, Object]; // {}[]
>e : {}[]
>[{}, Object] : {}[]
>[{}, Object] : (ObjectConstructor | {})[]
>{} : {}
>Object : ObjectConstructor
@ -48,7 +48,7 @@ var g = [[1], ['']]; // {}[]
>'' : ""
var h = [{ foo: 1, bar: '' }, { foo: 2 }]; // {foo: number}[]
>h : ({ foo: number; bar: string; } | { foo: number; })[]
>h : ({ foo: number; bar: string; } | { foo: number; bar?: undefined; })[]
>[{ foo: 1, bar: '' }, { foo: 2 }] : ({ foo: number; bar: string; } | { foo: number; })[]
>{ foo: 1, bar: '' } : { foo: number; bar: string; }
>foo : number
@ -60,7 +60,7 @@ var h = [{ foo: 1, bar: '' }, { foo: 2 }]; // {foo: number}[]
>2 : 2
var i = [{ foo: 1, bar: '' }, { foo: '' }]; // {}[]
>i : ({ foo: number; bar: string; } | { foo: string; })[]
>i : ({ foo: number; bar: string; } | { foo: string; bar?: undefined; })[]
>[{ foo: 1, bar: '' }, { foo: '' }] : ({ foo: number; bar: string; } | { foo: string; })[]
>{ foo: 1, bar: '' } : { foo: number; bar: string; }
>foo : number
@ -145,7 +145,7 @@ module Derived {
>Derived : typeof Derived
var h = [{ foo: base, basear: derived }, { foo: base }]; // {foo: Base}[]
>h : ({ foo: Base; basear: Derived; } | { foo: Base; })[]
>h : ({ foo: Base; basear: Derived; } | { foo: Base; basear?: undefined; })[]
>[{ foo: base, basear: derived }, { foo: base }] : ({ foo: Base; basear: Derived; } | { foo: Base; })[]
>{ foo: base, basear: derived } : { foo: Base; basear: Derived; }
>foo : Base
@ -157,7 +157,7 @@ module Derived {
>base : Base
var i = [{ foo: base, basear: derived }, { foo: derived }]; // {foo: Derived}[]
>i : ({ foo: Base; basear: Derived; } | { foo: Derived; })[]
>i : ({ foo: Base; basear: Derived; } | { foo: Derived; basear?: undefined; })[]
>[{ foo: base, basear: derived }, { foo: derived }] : ({ foo: Base; basear: Derived; } | { foo: Derived; })[]
>{ foo: base, basear: derived } : { foo: Base; basear: Derived; }
>foo : Base

View file

@ -176,7 +176,7 @@ var o1: { a: { a: string; }; b: string; } = { e: 0, f: 0 };
>0 : 0
var a1 = [{ e: 0, f: 0 }, { e: 0, f: 0 }, { e: 0, g: 0 }];
>a1 : ({ e: number; f: number; } | { e: number; g: number; })[]
>a1 : ({ e: number; f: number; g?: undefined; } | { e: number; g: number; f?: undefined; })[]
>[{ e: 0, f: 0 }, { e: 0, f: 0 }, { e: 0, g: 0 }] : ({ e: number; f: number; } | { e: number; g: number; })[]
>{ e: 0, f: 0 } : { e: number; f: number; }
>e : number

View file

@ -107,8 +107,8 @@ function fn3<T extends { a: string; b: string }, U extends { a: string; b: numbe
>u : U
var r3 = t || { a: '' };
>r3 : { a: string; }
>t || { a: '' } : { a: string; }
>r3 : T | { a: string; }
>t || { a: '' } : T | { a: string; }
>t : T
>{ a: '' } : { a: string; }
>a : string

View file

@ -0,0 +1,92 @@
tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts(7,1): error TS2322: Type '{ a: number; b: number; }' is not assignable to type '{ a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }'.
Type '{ a: number; b: number; }' is not assignable to type '{ a: number; b: string; c: boolean; }'.
Property 'c' is missing in type '{ a: number; b: number; }'.
tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts(8,1): error TS2322: Type '{ b: string; }' is not assignable to type '{ a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }'.
Type '{ b: string; }' is not assignable to type '{ a: number; b: string; c: boolean; }'.
Property 'a' is missing in type '{ b: string; }'.
tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts(9,1): error TS2322: Type '{ c: true; }' is not assignable to type '{ a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }'.
Type '{ c: true; }' is not assignable to type '{ a: number; b: string; c: boolean; }'.
Property 'a' is missing in type '{ c: true; }'.
tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts(17,1): error TS2322: Type '{ a: string; b: number; }' is not assignable to type '{ a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }'.
Type '{ a: string; b: number; }' is not assignable to type '{ a?: undefined; b?: undefined; }'.
Types of property 'a' are incompatible.
Type 'string' is not assignable to type 'undefined'.
tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts(18,1): error TS2322: Type '{ a: number; }' is not assignable to type '{ a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }'.
Type '{ a: number; }' is not assignable to type '{ a?: undefined; b?: undefined; }'.
Types of property 'a' are incompatible.
Type 'number' is not assignable to type 'undefined'.
==== tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts (5 errors) ====
// Object literals in unions are normalized upon widening
let a1 = [{ a: 0 }, { a: 1, b: "x" }, { a: 2, b: "y", c: true }][0];
a1.a; // number
a1.b; // string | undefined
a1.c; // boolean | undefined
a1 = { a: 1 };
a1 = { a: 0, b: 0 }; // Error
~~
!!! error TS2322: Type '{ a: number; b: number; }' is not assignable to type '{ a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }'.
!!! error TS2322: Type '{ a: number; b: number; }' is not assignable to type '{ a: number; b: string; c: boolean; }'.
!!! error TS2322: Property 'c' is missing in type '{ a: number; b: number; }'.
a1 = { b: "y" }; // Error
~~
!!! error TS2322: Type '{ b: string; }' is not assignable to type '{ a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }'.
!!! error TS2322: Type '{ b: string; }' is not assignable to type '{ a: number; b: string; c: boolean; }'.
!!! error TS2322: Property 'a' is missing in type '{ b: string; }'.
a1 = { c: true }; // Error
~~
!!! error TS2322: Type '{ c: true; }' is not assignable to type '{ a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }'.
!!! error TS2322: Type '{ c: true; }' is not assignable to type '{ a: number; b: string; c: boolean; }'.
!!! error TS2322: Property 'a' is missing in type '{ c: true; }'.
let a2 = [{ a: 1, b: 2 }, { a: "abc" }, {}][0];
a2.a; // string | number | undefined
a2.b; // number | undefined
a2 = { a: 10, b: 20 };
a2 = { a: "def" };
a2 = {};
a2 = { a: "def", b: 20 }; // Error
~~
!!! error TS2322: Type '{ a: string; b: number; }' is not assignable to type '{ a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }'.
!!! error TS2322: Type '{ a: string; b: number; }' is not assignable to type '{ a?: undefined; b?: undefined; }'.
!!! error TS2322: Types of property 'a' are incompatible.
!!! error TS2322: Type 'string' is not assignable to type 'undefined'.
a2 = { a: 1 }; // Error
~~
!!! error TS2322: Type '{ a: number; }' is not assignable to type '{ a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }'.
!!! error TS2322: Type '{ a: number; }' is not assignable to type '{ a?: undefined; b?: undefined; }'.
!!! error TS2322: Types of property 'a' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'undefined'.
// Object literals containing spreads are not normalized
declare let b1: { a: string, b: string } | { b: string, c: string };
let b2 = { ...b1, z: 55 };
let b3 = { ...b2 };
// Before widening {} acts like { [x: string]: undefined }, which is a
// subtype of types with all optional properties
declare let opts: { foo?: string, bar?: string, baz?: boolean };
let c1 = !true ? {} : opts;
let c2 = !true ? opts : {};
let c3 = !true ? { a: 0, b: 0 } : {};
let c4 = !true ? {} : { a: 0, b: 0 };
// Normalization applies to nested properties
let d1 = [{ kind: 'a', pos: { x: 0, y: 0 } }, { kind: 'b', pos: !true ? { a: "x" } : { b: 0 } }][0];
d1.kind;
d1.pos;
d1.pos.x;
d1.pos.y;
d1.pos.a;
d1.pos.b;
declare function f<T>(...items: T[]): T;
declare let data: { a: 1, b: "abc", c: true };
// Object literals are inferred as a single normalized union type
let e1 = f({ a: 1, b: 2 }, { a: "abc" }, {});
let e2 = f({}, { a: "abc" }, { a: 1, b: 2 });
let e3 = f(data, { a: 2 });
let e4 = f({ a: 2 }, data);

View file

@ -0,0 +1,232 @@
//// [objectLiteralNormalization.ts]
// Object literals in unions are normalized upon widening
let a1 = [{ a: 0 }, { a: 1, b: "x" }, { a: 2, b: "y", c: true }][0];
a1.a; // number
a1.b; // string | undefined
a1.c; // boolean | undefined
a1 = { a: 1 };
a1 = { a: 0, b: 0 }; // Error
a1 = { b: "y" }; // Error
a1 = { c: true }; // Error
let a2 = [{ a: 1, b: 2 }, { a: "abc" }, {}][0];
a2.a; // string | number | undefined
a2.b; // number | undefined
a2 = { a: 10, b: 20 };
a2 = { a: "def" };
a2 = {};
a2 = { a: "def", b: 20 }; // Error
a2 = { a: 1 }; // Error
// Object literals containing spreads are not normalized
declare let b1: { a: string, b: string } | { b: string, c: string };
let b2 = { ...b1, z: 55 };
let b3 = { ...b2 };
// Before widening {} acts like { [x: string]: undefined }, which is a
// subtype of types with all optional properties
declare let opts: { foo?: string, bar?: string, baz?: boolean };
let c1 = !true ? {} : opts;
let c2 = !true ? opts : {};
let c3 = !true ? { a: 0, b: 0 } : {};
let c4 = !true ? {} : { a: 0, b: 0 };
// Normalization applies to nested properties
let d1 = [{ kind: 'a', pos: { x: 0, y: 0 } }, { kind: 'b', pos: !true ? { a: "x" } : { b: 0 } }][0];
d1.kind;
d1.pos;
d1.pos.x;
d1.pos.y;
d1.pos.a;
d1.pos.b;
declare function f<T>(...items: T[]): T;
declare let data: { a: 1, b: "abc", c: true };
// Object literals are inferred as a single normalized union type
let e1 = f({ a: 1, b: 2 }, { a: "abc" }, {});
let e2 = f({}, { a: "abc" }, { a: 1, b: 2 });
let e3 = f(data, { a: 2 });
let e4 = f({ a: 2 }, data);
//// [objectLiteralNormalization.js]
"use strict";
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
// Object literals in unions are normalized upon widening
var a1 = [{ a: 0 }, { a: 1, b: "x" }, { a: 2, b: "y", c: true }][0];
a1.a; // number
a1.b; // string | undefined
a1.c; // boolean | undefined
a1 = { a: 1 };
a1 = { a: 0, b: 0 }; // Error
a1 = { b: "y" }; // Error
a1 = { c: true }; // Error
var a2 = [{ a: 1, b: 2 }, { a: "abc" }, {}][0];
a2.a; // string | number | undefined
a2.b; // number | undefined
a2 = { a: 10, b: 20 };
a2 = { a: "def" };
a2 = {};
a2 = { a: "def", b: 20 }; // Error
a2 = { a: 1 }; // Error
var b2 = __assign({}, b1, { z: 55 });
var b3 = __assign({}, b2);
var c1 = !true ? {} : opts;
var c2 = !true ? opts : {};
var c3 = !true ? { a: 0, b: 0 } : {};
var c4 = !true ? {} : { a: 0, b: 0 };
// Normalization applies to nested properties
var d1 = [{ kind: 'a', pos: { x: 0, y: 0 } }, { kind: 'b', pos: !true ? { a: "x" } : { b: 0 } }][0];
d1.kind;
d1.pos;
d1.pos.x;
d1.pos.y;
d1.pos.a;
d1.pos.b;
// Object literals are inferred as a single normalized union type
var e1 = f({ a: 1, b: 2 }, { a: "abc" }, {});
var e2 = f({}, { a: "abc" }, { a: 1, b: 2 });
var e3 = f(data, { a: 2 });
var e4 = f({ a: 2 }, data);
//// [objectLiteralNormalization.d.ts]
declare let a1: {
a: number;
b?: undefined;
c?: undefined;
} | {
a: number;
b: string;
c?: undefined;
} | {
a: number;
b: string;
c: boolean;
};
declare let a2: {
a: number;
b: number;
} | {
a: string;
b?: undefined;
} | {
a?: undefined;
b?: undefined;
};
declare let b1: {
a: string;
b: string;
} | {
b: string;
c: string;
};
declare let b2: {
z: number;
a: string;
b: string;
} | {
z: number;
b: string;
c: string;
};
declare let b3: {
z: number;
a: string;
b: string;
} | {
z: number;
b: string;
c: string;
};
declare let opts: {
foo?: string;
bar?: string;
baz?: boolean;
};
declare let c1: {
foo?: string | undefined;
bar?: string | undefined;
baz?: boolean | undefined;
};
declare let c2: {
foo?: string | undefined;
bar?: string | undefined;
baz?: boolean | undefined;
};
declare let c3: {
a: number;
b: number;
} | {
a?: undefined;
b?: undefined;
};
declare let c4: {
a?: undefined;
b?: undefined;
} | {
a: number;
b: number;
};
declare let d1: {
kind: string;
pos: {
x: number;
y: number;
a?: undefined;
b?: undefined;
};
} | {
kind: string;
pos: {
a: string;
x?: undefined;
y?: undefined;
b?: undefined;
} | {
b: number;
x?: undefined;
y?: undefined;
a?: undefined;
};
};
declare function f<T>(...items: T[]): T;
declare let data: {
a: 1;
b: "abc";
c: true;
};
declare let e1: {
a: number;
b: number;
} | {
a: string;
b?: undefined;
} | {
a?: undefined;
b?: undefined;
};
declare let e2: {
a?: undefined;
b?: undefined;
} | {
a: string;
b?: undefined;
} | {
a: number;
b: number;
};
declare let e3: {
a: number;
};
declare let e4: {
a: number;
};

View file

@ -0,0 +1,213 @@
=== tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts ===
// Object literals in unions are normalized upon widening
let a1 = [{ a: 0 }, { a: 1, b: "x" }, { a: 2, b: "y", c: true }][0];
>a1 : Symbol(a1, Decl(objectLiteralNormalization.ts, 1, 3))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 1, 11))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 1, 21))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 1, 27))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 1, 39))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 1, 45))
>c : Symbol(c, Decl(objectLiteralNormalization.ts, 1, 53))
a1.a; // number
>a1.a : Symbol(a, Decl(objectLiteralNormalization.ts, 1, 11), Decl(objectLiteralNormalization.ts, 1, 21), Decl(objectLiteralNormalization.ts, 1, 39))
>a1 : Symbol(a1, Decl(objectLiteralNormalization.ts, 1, 3))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 1, 11), Decl(objectLiteralNormalization.ts, 1, 21), Decl(objectLiteralNormalization.ts, 1, 39))
a1.b; // string | undefined
>a1.b : Symbol(b, Decl(objectLiteralNormalization.ts, 1, 27), Decl(objectLiteralNormalization.ts, 1, 45))
>a1 : Symbol(a1, Decl(objectLiteralNormalization.ts, 1, 3))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 1, 27), Decl(objectLiteralNormalization.ts, 1, 45))
a1.c; // boolean | undefined
>a1.c : Symbol(c, Decl(objectLiteralNormalization.ts, 1, 53))
>a1 : Symbol(a1, Decl(objectLiteralNormalization.ts, 1, 3))
>c : Symbol(c, Decl(objectLiteralNormalization.ts, 1, 53))
a1 = { a: 1 };
>a1 : Symbol(a1, Decl(objectLiteralNormalization.ts, 1, 3))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 5, 6))
a1 = { a: 0, b: 0 }; // Error
>a1 : Symbol(a1, Decl(objectLiteralNormalization.ts, 1, 3))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 6, 6))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 6, 12))
a1 = { b: "y" }; // Error
>a1 : Symbol(a1, Decl(objectLiteralNormalization.ts, 1, 3))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 7, 6))
a1 = { c: true }; // Error
>a1 : Symbol(a1, Decl(objectLiteralNormalization.ts, 1, 3))
>c : Symbol(c, Decl(objectLiteralNormalization.ts, 8, 6))
let a2 = [{ a: 1, b: 2 }, { a: "abc" }, {}][0];
>a2 : Symbol(a2, Decl(objectLiteralNormalization.ts, 10, 3))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 10, 11))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 10, 17))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 10, 27))
a2.a; // string | number | undefined
>a2.a : Symbol(a, Decl(objectLiteralNormalization.ts, 10, 11), Decl(objectLiteralNormalization.ts, 10, 27))
>a2 : Symbol(a2, Decl(objectLiteralNormalization.ts, 10, 3))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 10, 11), Decl(objectLiteralNormalization.ts, 10, 27))
a2.b; // number | undefined
>a2.b : Symbol(b, Decl(objectLiteralNormalization.ts, 10, 17))
>a2 : Symbol(a2, Decl(objectLiteralNormalization.ts, 10, 3))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 10, 17))
a2 = { a: 10, b: 20 };
>a2 : Symbol(a2, Decl(objectLiteralNormalization.ts, 10, 3))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 13, 6))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 13, 13))
a2 = { a: "def" };
>a2 : Symbol(a2, Decl(objectLiteralNormalization.ts, 10, 3))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 14, 6))
a2 = {};
>a2 : Symbol(a2, Decl(objectLiteralNormalization.ts, 10, 3))
a2 = { a: "def", b: 20 }; // Error
>a2 : Symbol(a2, Decl(objectLiteralNormalization.ts, 10, 3))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 16, 6))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 16, 16))
a2 = { a: 1 }; // Error
>a2 : Symbol(a2, Decl(objectLiteralNormalization.ts, 10, 3))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 17, 6))
// Object literals containing spreads are not normalized
declare let b1: { a: string, b: string } | { b: string, c: string };
>b1 : Symbol(b1, Decl(objectLiteralNormalization.ts, 20, 11))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 20, 17))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 20, 28))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 20, 44))
>c : Symbol(c, Decl(objectLiteralNormalization.ts, 20, 55))
let b2 = { ...b1, z: 55 };
>b2 : Symbol(b2, Decl(objectLiteralNormalization.ts, 21, 3))
>b1 : Symbol(b1, Decl(objectLiteralNormalization.ts, 20, 11))
>z : Symbol(z, Decl(objectLiteralNormalization.ts, 21, 17))
let b3 = { ...b2 };
>b3 : Symbol(b3, Decl(objectLiteralNormalization.ts, 22, 3))
>b2 : Symbol(b2, Decl(objectLiteralNormalization.ts, 21, 3))
// Before widening {} acts like { [x: string]: undefined }, which is a
// subtype of types with all optional properties
declare let opts: { foo?: string, bar?: string, baz?: boolean };
>opts : Symbol(opts, Decl(objectLiteralNormalization.ts, 26, 11))
>foo : Symbol(foo, Decl(objectLiteralNormalization.ts, 26, 19))
>bar : Symbol(bar, Decl(objectLiteralNormalization.ts, 26, 33))
>baz : Symbol(baz, Decl(objectLiteralNormalization.ts, 26, 47))
let c1 = !true ? {} : opts;
>c1 : Symbol(c1, Decl(objectLiteralNormalization.ts, 27, 3))
>opts : Symbol(opts, Decl(objectLiteralNormalization.ts, 26, 11))
let c2 = !true ? opts : {};
>c2 : Symbol(c2, Decl(objectLiteralNormalization.ts, 28, 3))
>opts : Symbol(opts, Decl(objectLiteralNormalization.ts, 26, 11))
let c3 = !true ? { a: 0, b: 0 } : {};
>c3 : Symbol(c3, Decl(objectLiteralNormalization.ts, 29, 3))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 29, 18))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 29, 24))
let c4 = !true ? {} : { a: 0, b: 0 };
>c4 : Symbol(c4, Decl(objectLiteralNormalization.ts, 30, 3))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 30, 23))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 30, 29))
// Normalization applies to nested properties
let d1 = [{ kind: 'a', pos: { x: 0, y: 0 } }, { kind: 'b', pos: !true ? { a: "x" } : { b: 0 } }][0];
>d1 : Symbol(d1, Decl(objectLiteralNormalization.ts, 33, 3))
>kind : Symbol(kind, Decl(objectLiteralNormalization.ts, 33, 11))
>pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22))
>x : Symbol(x, Decl(objectLiteralNormalization.ts, 33, 29))
>y : Symbol(y, Decl(objectLiteralNormalization.ts, 33, 35))
>kind : Symbol(kind, Decl(objectLiteralNormalization.ts, 33, 47))
>pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 58))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 33, 73))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 33, 86))
d1.kind;
>d1.kind : Symbol(kind, Decl(objectLiteralNormalization.ts, 33, 11), Decl(objectLiteralNormalization.ts, 33, 47))
>d1 : Symbol(d1, Decl(objectLiteralNormalization.ts, 33, 3))
>kind : Symbol(kind, Decl(objectLiteralNormalization.ts, 33, 11), Decl(objectLiteralNormalization.ts, 33, 47))
d1.pos;
>d1.pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>d1 : Symbol(d1, Decl(objectLiteralNormalization.ts, 33, 3))
>pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
d1.pos.x;
>d1.pos.x : Symbol(x, Decl(objectLiteralNormalization.ts, 33, 29))
>d1.pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>d1 : Symbol(d1, Decl(objectLiteralNormalization.ts, 33, 3))
>pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>x : Symbol(x, Decl(objectLiteralNormalization.ts, 33, 29))
d1.pos.y;
>d1.pos.y : Symbol(y, Decl(objectLiteralNormalization.ts, 33, 35))
>d1.pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>d1 : Symbol(d1, Decl(objectLiteralNormalization.ts, 33, 3))
>pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>y : Symbol(y, Decl(objectLiteralNormalization.ts, 33, 35))
d1.pos.a;
>d1.pos.a : Symbol(a, Decl(objectLiteralNormalization.ts, 33, 73))
>d1.pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>d1 : Symbol(d1, Decl(objectLiteralNormalization.ts, 33, 3))
>pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 33, 73))
d1.pos.b;
>d1.pos.b : Symbol(b, Decl(objectLiteralNormalization.ts, 33, 86))
>d1.pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>d1 : Symbol(d1, Decl(objectLiteralNormalization.ts, 33, 3))
>pos : Symbol(pos, Decl(objectLiteralNormalization.ts, 33, 22), Decl(objectLiteralNormalization.ts, 33, 58))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 33, 86))
declare function f<T>(...items: T[]): T;
>f : Symbol(f, Decl(objectLiteralNormalization.ts, 39, 9))
>T : Symbol(T, Decl(objectLiteralNormalization.ts, 41, 19))
>items : Symbol(items, Decl(objectLiteralNormalization.ts, 41, 22))
>T : Symbol(T, Decl(objectLiteralNormalization.ts, 41, 19))
>T : Symbol(T, Decl(objectLiteralNormalization.ts, 41, 19))
declare let data: { a: 1, b: "abc", c: true };
>data : Symbol(data, Decl(objectLiteralNormalization.ts, 42, 11))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 42, 19))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 42, 25))
>c : Symbol(c, Decl(objectLiteralNormalization.ts, 42, 35))
// Object literals are inferred as a single normalized union type
let e1 = f({ a: 1, b: 2 }, { a: "abc" }, {});
>e1 : Symbol(e1, Decl(objectLiteralNormalization.ts, 45, 3))
>f : Symbol(f, Decl(objectLiteralNormalization.ts, 39, 9))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 45, 12))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 45, 18))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 45, 28))
let e2 = f({}, { a: "abc" }, { a: 1, b: 2 });
>e2 : Symbol(e2, Decl(objectLiteralNormalization.ts, 46, 3))
>f : Symbol(f, Decl(objectLiteralNormalization.ts, 39, 9))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 46, 16))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 46, 30))
>b : Symbol(b, Decl(objectLiteralNormalization.ts, 46, 36))
let e3 = f(data, { a: 2 });
>e3 : Symbol(e3, Decl(objectLiteralNormalization.ts, 47, 3))
>f : Symbol(f, Decl(objectLiteralNormalization.ts, 39, 9))
>data : Symbol(data, Decl(objectLiteralNormalization.ts, 42, 11))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 47, 18))
let e4 = f({ a: 2 }, data);
>e4 : Symbol(e4, Decl(objectLiteralNormalization.ts, 48, 3))
>f : Symbol(f, Decl(objectLiteralNormalization.ts, 39, 9))
>a : Symbol(a, Decl(objectLiteralNormalization.ts, 48, 12))
>data : Symbol(data, Decl(objectLiteralNormalization.ts, 42, 11))

View file

@ -0,0 +1,326 @@
=== tests/cases/conformance/expressions/objectLiterals/objectLiteralNormalization.ts ===
// Object literals in unions are normalized upon widening
let a1 = [{ a: 0 }, { a: 1, b: "x" }, { a: 2, b: "y", c: true }][0];
>a1 : { a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }
>[{ a: 0 }, { a: 1, b: "x" }, { a: 2, b: "y", c: true }][0] : { a: number; } | { a: number; b: string; } | { a: number; b: string; c: boolean; }
>[{ a: 0 }, { a: 1, b: "x" }, { a: 2, b: "y", c: true }] : ({ a: number; } | { a: number; b: string; } | { a: number; b: string; c: boolean; })[]
>{ a: 0 } : { a: number; }
>a : number
>0 : 0
>{ a: 1, b: "x" } : { a: number; b: string; }
>a : number
>1 : 1
>b : string
>"x" : "x"
>{ a: 2, b: "y", c: true } : { a: number; b: string; c: boolean; }
>a : number
>2 : 2
>b : string
>"y" : "y"
>c : boolean
>true : true
>0 : 0
a1.a; // number
>a1.a : number
>a1 : { a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }
>a : number
a1.b; // string | undefined
>a1.b : string | undefined
>a1 : { a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }
>b : string | undefined
a1.c; // boolean | undefined
>a1.c : boolean | undefined
>a1 : { a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }
>c : boolean | undefined
a1 = { a: 1 };
>a1 = { a: 1 } : { a: number; }
>a1 : { a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
a1 = { a: 0, b: 0 }; // Error
>a1 = { a: 0, b: 0 } : { a: number; b: number; }
>a1 : { a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }
>{ a: 0, b: 0 } : { a: number; b: number; }
>a : number
>0 : 0
>b : number
>0 : 0
a1 = { b: "y" }; // Error
>a1 = { b: "y" } : { b: string; }
>a1 : { a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }
>{ b: "y" } : { b: string; }
>b : string
>"y" : "y"
a1 = { c: true }; // Error
>a1 = { c: true } : { c: true; }
>a1 : { a: number; b?: undefined; c?: undefined; } | { a: number; b: string; c?: undefined; } | { a: number; b: string; c: boolean; }
>{ c: true } : { c: true; }
>c : boolean
>true : true
let a2 = [{ a: 1, b: 2 }, { a: "abc" }, {}][0];
>a2 : { a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }
>[{ a: 1, b: 2 }, { a: "abc" }, {}][0] : { a: number; b: number; } | { a: string; } | {}
>[{ a: 1, b: 2 }, { a: "abc" }, {}] : ({ a: number; b: number; } | { a: string; } | {})[]
>{ a: 1, b: 2 } : { a: number; b: number; }
>a : number
>1 : 1
>b : number
>2 : 2
>{ a: "abc" } : { a: string; }
>a : string
>"abc" : "abc"
>{} : {}
>0 : 0
a2.a; // string | number | undefined
>a2.a : string | number | undefined
>a2 : { a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }
>a : string | number | undefined
a2.b; // number | undefined
>a2.b : number | undefined
>a2 : { a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }
>b : number | undefined
a2 = { a: 10, b: 20 };
>a2 = { a: 10, b: 20 } : { a: number; b: number; }
>a2 : { a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }
>{ a: 10, b: 20 } : { a: number; b: number; }
>a : number
>10 : 10
>b : number
>20 : 20
a2 = { a: "def" };
>a2 = { a: "def" } : { a: string; }
>a2 : { a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }
>{ a: "def" } : { a: string; }
>a : string
>"def" : "def"
a2 = {};
>a2 = {} : {}
>a2 : { a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }
>{} : {}
a2 = { a: "def", b: 20 }; // Error
>a2 = { a: "def", b: 20 } : { a: string; b: number; }
>a2 : { a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }
>{ a: "def", b: 20 } : { a: string; b: number; }
>a : string
>"def" : "def"
>b : number
>20 : 20
a2 = { a: 1 }; // Error
>a2 = { a: 1 } : { a: number; }
>a2 : { a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
// Object literals containing spreads are not normalized
declare let b1: { a: string, b: string } | { b: string, c: string };
>b1 : { a: string; b: string; } | { b: string; c: string; }
>a : string
>b : string
>b : string
>c : string
let b2 = { ...b1, z: 55 };
>b2 : { z: number; a: string; b: string; } | { z: number; b: string; c: string; }
>{ ...b1, z: 55 } : { z: number; a: string; b: string; } | { z: number; b: string; c: string; }
>b1 : { a: string; b: string; } | { b: string; c: string; }
>z : number
>55 : 55
let b3 = { ...b2 };
>b3 : { z: number; a: string; b: string; } | { z: number; b: string; c: string; }
>{ ...b2 } : { z: number; a: string; b: string; } | { z: number; b: string; c: string; }
>b2 : { z: number; a: string; b: string; } | { z: number; b: string; c: string; }
// Before widening {} acts like { [x: string]: undefined }, which is a
// subtype of types with all optional properties
declare let opts: { foo?: string, bar?: string, baz?: boolean };
>opts : { foo?: string | undefined; bar?: string | undefined; baz?: boolean | undefined; }
>foo : string | undefined
>bar : string | undefined
>baz : boolean | undefined
let c1 = !true ? {} : opts;
>c1 : { foo?: string | undefined; bar?: string | undefined; baz?: boolean | undefined; }
>!true ? {} : opts : { foo?: string | undefined; bar?: string | undefined; baz?: boolean | undefined; }
>!true : false
>true : true
>{} : {}
>opts : { foo?: string | undefined; bar?: string | undefined; baz?: boolean | undefined; }
let c2 = !true ? opts : {};
>c2 : { foo?: string | undefined; bar?: string | undefined; baz?: boolean | undefined; }
>!true ? opts : {} : { foo?: string | undefined; bar?: string | undefined; baz?: boolean | undefined; }
>!true : false
>true : true
>opts : { foo?: string | undefined; bar?: string | undefined; baz?: boolean | undefined; }
>{} : {}
let c3 = !true ? { a: 0, b: 0 } : {};
>c3 : { a: number; b: number; } | { a?: undefined; b?: undefined; }
>!true ? { a: 0, b: 0 } : {} : { a: number; b: number; } | {}
>!true : false
>true : true
>{ a: 0, b: 0 } : { a: number; b: number; }
>a : number
>0 : 0
>b : number
>0 : 0
>{} : {}
let c4 = !true ? {} : { a: 0, b: 0 };
>c4 : { a?: undefined; b?: undefined; } | { a: number; b: number; }
>!true ? {} : { a: 0, b: 0 } : {} | { a: number; b: number; }
>!true : false
>true : true
>{} : {}
>{ a: 0, b: 0 } : { a: number; b: number; }
>a : number
>0 : 0
>b : number
>0 : 0
// Normalization applies to nested properties
let d1 = [{ kind: 'a', pos: { x: 0, y: 0 } }, { kind: 'b', pos: !true ? { a: "x" } : { b: 0 } }][0];
>d1 : { kind: string; pos: { x: number; y: number; a?: undefined; b?: undefined; }; } | { kind: string; pos: { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }; }
>[{ kind: 'a', pos: { x: 0, y: 0 } }, { kind: 'b', pos: !true ? { a: "x" } : { b: 0 } }][0] : { kind: string; pos: { x: number; y: number; }; } | { kind: string; pos: { a: string; } | { b: number; }; }
>[{ kind: 'a', pos: { x: 0, y: 0 } }, { kind: 'b', pos: !true ? { a: "x" } : { b: 0 } }] : ({ kind: string; pos: { x: number; y: number; }; } | { kind: string; pos: { a: string; } | { b: number; }; })[]
>{ kind: 'a', pos: { x: 0, y: 0 } } : { kind: string; pos: { x: number; y: number; }; }
>kind : string
>'a' : "a"
>pos : { x: number; y: number; }
>{ x: 0, y: 0 } : { x: number; y: number; }
>x : number
>0 : 0
>y : number
>0 : 0
>{ kind: 'b', pos: !true ? { a: "x" } : { b: 0 } } : { kind: string; pos: { a: string; } | { b: number; }; }
>kind : string
>'b' : "b"
>pos : { a: string; } | { b: number; }
>!true ? { a: "x" } : { b: 0 } : { a: string; } | { b: number; }
>!true : false
>true : true
>{ a: "x" } : { a: string; }
>a : string
>"x" : "x"
>{ b: 0 } : { b: number; }
>b : number
>0 : 0
>0 : 0
d1.kind;
>d1.kind : string
>d1 : { kind: string; pos: { x: number; y: number; a?: undefined; b?: undefined; }; } | { kind: string; pos: { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }; }
>kind : string
d1.pos;
>d1.pos : { x: number; y: number; a?: undefined; b?: undefined; } | { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }
>d1 : { kind: string; pos: { x: number; y: number; a?: undefined; b?: undefined; }; } | { kind: string; pos: { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }; }
>pos : { x: number; y: number; a?: undefined; b?: undefined; } | { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }
d1.pos.x;
>d1.pos.x : number | undefined
>d1.pos : { x: number; y: number; a?: undefined; b?: undefined; } | { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }
>d1 : { kind: string; pos: { x: number; y: number; a?: undefined; b?: undefined; }; } | { kind: string; pos: { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }; }
>pos : { x: number; y: number; a?: undefined; b?: undefined; } | { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }
>x : number | undefined
d1.pos.y;
>d1.pos.y : number | undefined
>d1.pos : { x: number; y: number; a?: undefined; b?: undefined; } | { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }
>d1 : { kind: string; pos: { x: number; y: number; a?: undefined; b?: undefined; }; } | { kind: string; pos: { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }; }
>pos : { x: number; y: number; a?: undefined; b?: undefined; } | { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }
>y : number | undefined
d1.pos.a;
>d1.pos.a : string | undefined
>d1.pos : { x: number; y: number; a?: undefined; b?: undefined; } | { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }
>d1 : { kind: string; pos: { x: number; y: number; a?: undefined; b?: undefined; }; } | { kind: string; pos: { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }; }
>pos : { x: number; y: number; a?: undefined; b?: undefined; } | { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }
>a : string | undefined
d1.pos.b;
>d1.pos.b : number | undefined
>d1.pos : { x: number; y: number; a?: undefined; b?: undefined; } | { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }
>d1 : { kind: string; pos: { x: number; y: number; a?: undefined; b?: undefined; }; } | { kind: string; pos: { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }; }
>pos : { x: number; y: number; a?: undefined; b?: undefined; } | { a: string; x?: undefined; y?: undefined; b?: undefined; } | { b: number; x?: undefined; y?: undefined; a?: undefined; }
>b : number | undefined
declare function f<T>(...items: T[]): T;
>f : <T>(...items: T[]) => T
>T : T
>items : T[]
>T : T
>T : T
declare let data: { a: 1, b: "abc", c: true };
>data : { a: 1; b: "abc"; c: true; }
>a : 1
>b : "abc"
>c : true
>true : true
// Object literals are inferred as a single normalized union type
let e1 = f({ a: 1, b: 2 }, { a: "abc" }, {});
>e1 : { a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }
>f({ a: 1, b: 2 }, { a: "abc" }, {}) : { a: number; b: number; } | { a: string; b?: undefined; } | { a?: undefined; b?: undefined; }
>f : <T>(...items: T[]) => T
>{ a: 1, b: 2 } : { a: number; b: number; }
>a : number
>1 : 1
>b : number
>2 : 2
>{ a: "abc" } : { a: string; }
>a : string
>"abc" : "abc"
>{} : {}
let e2 = f({}, { a: "abc" }, { a: 1, b: 2 });
>e2 : { a?: undefined; b?: undefined; } | { a: string; b?: undefined; } | { a: number; b: number; }
>f({}, { a: "abc" }, { a: 1, b: 2 }) : { a?: undefined; b?: undefined; } | { a: string; b?: undefined; } | { a: number; b: number; }
>f : <T>(...items: T[]) => T
>{} : {}
>{ a: "abc" } : { a: string; }
>a : string
>"abc" : "abc"
>{ a: 1, b: 2 } : { a: number; b: number; }
>a : number
>1 : 1
>b : number
>2 : 2
let e3 = f(data, { a: 2 });
>e3 : { a: number; }
>f(data, { a: 2 }) : { a: number; }
>f : <T>(...items: T[]) => T
>data : { a: 1; b: "abc"; c: true; }
>{ a: 2 } : { a: number; }
>a : number
>2 : 2
let e4 = f({ a: 2 }, data);
>e4 : { a: number; }
>f({ a: 2 }, data) : { a: number; }
>f : <T>(...items: T[]) => T
>{ a: 2 } : { a: number; }
>a : number
>2 : 2
>data : { a: 1; b: "abc"; c: true; }

View file

@ -295,7 +295,7 @@ function conditionalSpreadBoolean(b: boolean) : { x: number, y: number } {
>14 : 14
}
let o2 = { ...b && { x: 21 }}
>o2 : {} | { x: number; }
>o2 : {}
>{ ...b && { x: 21 }} : {} | { x: number; }
>b && { x: 21 } : false | { x: number; }
>b : boolean
@ -336,7 +336,7 @@ function conditionalSpreadNumber(nt: number): { x: number, y: number } {
>nt : number
}
let o2 = { ...nt && { x: nt }}
>o2 : {} | { x: number; }
>o2 : {}
>{ ...nt && { x: nt }} : {} | { x: number; }
>nt && { x: nt } : 0 | { x: number; }
>nt : number
@ -377,7 +377,7 @@ function conditionalSpreadString(st: string): { x: string, y: number } {
>st : string
}
let o2 = { ...st && { x: st }}
>o2 : {} | { x: string; }
>o2 : {}
>{ ...st && { x: st }} : {} | { x: string; }
>st && { x: st } : "" | { x: string; }
>st : string

View file

@ -78,7 +78,7 @@ var b: Boolean = true;
var n3 = 5 || {};
>n3 : {}
>5 || {} : {}
>5 || {} : 5 | {}
>5 : 5
>{} : {}

View file

@ -0,0 +1,41 @@
tests/cases/conformance/types/spread/spreadUnion2.ts(5,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o1' has type '{} | { a: number; }' at tests/cases/conformance/types/spread/spreadUnion2.ts 3:4, but here has type '{}'.
tests/cases/conformance/types/spread/spreadUnion2.ts(8,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o2' has type '{} | { b: number; }' at tests/cases/conformance/types/spread/spreadUnion2.ts 6:4, but here has type '{}'.
tests/cases/conformance/types/spread/spreadUnion2.ts(11,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o3' has type '{} | { a: number; } | { b: number; } | { a: number; b: number; }' at tests/cases/conformance/types/spread/spreadUnion2.ts 9:4, but here has type '{}'.
tests/cases/conformance/types/spread/spreadUnion2.ts(12,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o3' has type '{} | { a: number; } | { b: number; } | { a: number; b: number; }' at tests/cases/conformance/types/spread/spreadUnion2.ts 9:4, but here has type '{}'.
tests/cases/conformance/types/spread/spreadUnion2.ts(15,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o4' has type '{} | { a: number; }' at tests/cases/conformance/types/spread/spreadUnion2.ts 13:4, but here has type '{}'.
tests/cases/conformance/types/spread/spreadUnion2.ts(18,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o5' has type '{} | { b: number; }' at tests/cases/conformance/types/spread/spreadUnion2.ts 16:4, but here has type '{}'.
==== tests/cases/conformance/types/spread/spreadUnion2.ts (6 errors) ====
declare const undefinedUnion: { a: number } | undefined;
declare const nullUnion: { b: number } | null;
var o1: {} | { a: number };
var o1 = { ...undefinedUnion };
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o1' has type '{} | { a: number; }' at tests/cases/conformance/types/spread/spreadUnion2.ts 3:4, but here has type '{}'.
var o2: {} | { b: number };
var o2 = { ...nullUnion };
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o2' has type '{} | { b: number; }' at tests/cases/conformance/types/spread/spreadUnion2.ts 6:4, but here has type '{}'.
var o3: {} | { a: number } | { b: number } | { a: number, b: number };
var o3 = { ...undefinedUnion, ...nullUnion };
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o3' has type '{} | { a: number; } | { b: number; } | { a: number; b: number; }' at tests/cases/conformance/types/spread/spreadUnion2.ts 9:4, but here has type '{}'.
var o3 = { ...nullUnion, ...undefinedUnion };
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o3' has type '{} | { a: number; } | { b: number; } | { a: number; b: number; }' at tests/cases/conformance/types/spread/spreadUnion2.ts 9:4, but here has type '{}'.
var o4: {} | { a: number };
var o4 = { ...undefinedUnion, ...undefinedUnion };
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o4' has type '{} | { a: number; }' at tests/cases/conformance/types/spread/spreadUnion2.ts 13:4, but here has type '{}'.
var o5: {} | { b: number };
var o5 = { ...nullUnion, ...nullUnion };
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o5' has type '{} | { b: number; }' at tests/cases/conformance/types/spread/spreadUnion2.ts 16:4, but here has type '{}'.

View file

@ -2,8 +2,7 @@ tests/cases/conformance/types/spread/spreadUnion3.ts(2,5): error TS2322: Type '{
Type '{ y: number; }' is not assignable to type '{ y: string; }'.
Types of property 'y' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/types/spread/spreadUnion3.ts(9,23): error TS2339: Property 'a' does not exist on type '{} | {} | { a: number; }'.
Property 'a' does not exist on type '{}'.
tests/cases/conformance/types/spread/spreadUnion3.ts(9,23): error TS2339: Property 'a' does not exist on type '{}'.
tests/cases/conformance/types/spread/spreadUnion3.ts(17,11): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/spreadUnion3.ts(18,11): error TS2698: Spread types may only be created from object types.
@ -24,8 +23,7 @@ tests/cases/conformance/types/spread/spreadUnion3.ts(18,11): error TS2698: Sprea
let b = { ...t };
let c: number = b.a; // might not have 'a'
~
!!! error TS2339: Property 'a' does not exist on type '{} | {} | { a: number; }'.
!!! error TS2339: Property 'a' does not exist on type '{}'.
!!! error TS2339: Property 'a' does not exist on type '{}'.
}
g()
g(undefined)

View file

@ -24,14 +24,14 @@ function g(t?: { a: number } | null): void {
>null : null
let b = { ...t };
>b : {} | {} | { a: number; }
>b : {}
>{ ...t } : {} | {} | { a: number; }
>t : { a: number; } | null | undefined
let c: number = b.a; // might not have 'a'
>c : number
>b.a : any
>b : {} | {} | { a: number; }
>b : {}
>a : any
}
g()

View file

@ -676,14 +676,14 @@ function f21<T extends Number>(x: T) {
var r20 = true ? {} : x; // ok
>r20 : {}
>true ? {} : x : {}
>true ? {} : x : T | {}
>true : true
>{} : {}
>x : T
var r20 = true ? x : {}; // ok
>r20 : {}
>true ? x : {} : {}
>true ? x : {} : T | {}
>true : true
>x : T
>{} : {}

View file

@ -13,8 +13,8 @@ Symbol instanceof Symbol();
(Symbol() || {}) instanceof Object; // This one should be okay, it's a valid way of distinguishing types
>(Symbol() || {}) instanceof Object : boolean
>(Symbol() || {}) : {}
>Symbol() || {} : {}
>(Symbol() || {}) : symbol | {}
>Symbol() || {} : symbol | {}
>Symbol() : symbol
>Symbol : SymbolConstructor
>{} : {}
@ -23,8 +23,8 @@ Symbol instanceof Symbol();
Symbol instanceof (Symbol() || {});
>Symbol instanceof (Symbol() || {}) : boolean
>Symbol : SymbolConstructor
>(Symbol() || {}) : {}
>Symbol() || {} : {}
>(Symbol() || {}) : symbol | {}
>Symbol() || {} : symbol | {}
>Symbol() : symbol
>Symbol : SymbolConstructor
>{} : {}

View file

@ -33,7 +33,7 @@ s || 1;
>1 : 1
({}) || s;
>({}) || s : {}
>({}) || s : symbol | {}
>({}) : {}
>{} : {}
>s : symbol

View file

@ -1,6 +1,5 @@
tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInference.ts(62,36): error TS2345: Argument of type '0' is not assignable to parameter of type '""'.
tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInference.ts(75,79): error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type '{ x: number; z: Date; }'.
Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; z: Date; }'.
tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInference.ts(76,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'a9e' has type '{ x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }' at tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInference.ts 74:4, but here has type '{}'.
==== tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInference.ts (2 errors) ====
@ -81,10 +80,9 @@ tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInference
}
var a9e = someGenerics9 `${ undefined }${ { x: 6, z: new Date() } }${ { x: 6, y: '' } }`;
~~~~~
!!! error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type '{ x: number; z: Date; }'.
!!! error TS2345: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; z: Date; }'.
var a9e: {};
~~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'a9e' has type '{ x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }' at tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInference.ts 74:4, but here has type '{}'.
// Generic tag with multiple parameters of generic type passed arguments with a single best common type
var a9d = someGenerics9 `${ { x: 3 }}${ { x: 6 }}${ { x: 6 } }`;

View file

@ -395,8 +395,8 @@ interface A92 {
}
var a9e = someGenerics9 `${ undefined }${ { x: 6, z: new Date() } }${ { x: 6, y: '' } }`;
>a9e : any
>someGenerics9 `${ undefined }${ { x: 6, z: new Date() } }${ { x: 6, y: '' } }` : any
>a9e : { x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }
>someGenerics9 `${ undefined }${ { x: 6, z: new Date() } }${ { x: 6, y: '' } }` : { x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }
>someGenerics9 : <T>(strs: TemplateStringsArray, a: T, b: T, c: T) => T
>`${ undefined }${ { x: 6, z: new Date() } }${ { x: 6, y: '' } }` : string
>undefined : undefined
@ -413,7 +413,7 @@ var a9e = someGenerics9 `${ undefined }${ { x: 6, z: new Date() } }${ { x: 6, y:
>'' : ""
var a9e: {};
>a9e : any
>a9e : { x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }
// Generic tag with multiple parameters of generic type passed arguments with a single best common type
var a9d = someGenerics9 `${ { x: 3 }}${ { x: 6 }}${ { x: 6 } }`;

View file

@ -1,6 +1,5 @@
tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInferenceES6.ts(62,36): error TS2345: Argument of type '0' is not assignable to parameter of type '""'.
tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInferenceES6.ts(75,79): error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type '{ x: number; z: Date; }'.
Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; z: Date; }'.
tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInferenceES6.ts(76,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'a9e' has type '{ x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }' at tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInferenceES6.ts 74:4, but here has type '{}'.
==== tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInferenceES6.ts (2 errors) ====
@ -81,10 +80,9 @@ tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInference
}
var a9e = someGenerics9 `${ undefined }${ { x: 6, z: new Date() } }${ { x: 6, y: '' } }`;
~~~~~
!!! error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type '{ x: number; z: Date; }'.
!!! error TS2345: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; z: Date; }'.
var a9e: {};
~~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'a9e' has type '{ x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }' at tests/cases/conformance/es6/templates/taggedTemplateStringsTypeArgumentInferenceES6.ts 74:4, but here has type '{}'.
// Generic tag with multiple parameters of generic type passed arguments with a single best common type
var a9d = someGenerics9 `${ { x: 3 }}${ { x: 6 }}${ { x: 6 } }`;

View file

@ -395,8 +395,8 @@ interface A92 {
}
var a9e = someGenerics9 `${ undefined }${ { x: 6, z: new Date() } }${ { x: 6, y: '' } }`;
>a9e : any
>someGenerics9 `${ undefined }${ { x: 6, z: new Date() } }${ { x: 6, y: '' } }` : any
>a9e : { x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }
>someGenerics9 `${ undefined }${ { x: 6, z: new Date() } }${ { x: 6, y: '' } }` : { x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }
>someGenerics9 : <T>(strs: TemplateStringsArray, a: T, b: T, c: T) => T
>`${ undefined }${ { x: 6, z: new Date() } }${ { x: 6, y: '' } }` : string
>undefined : undefined
@ -413,7 +413,7 @@ var a9e = someGenerics9 `${ undefined }${ { x: 6, z: new Date() } }${ { x: 6, y:
>'' : ""
var a9e: {};
>a9e : any
>a9e : { x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }
// Generic tag with multiple parameters of generic type passed arguments with a single best common type
var a9d = someGenerics9 `${ { x: 3 }}${ { x: 6 }}${ { x: 6 } }`;

View file

@ -1,20 +0,0 @@
tests/cases/compiler/typeArgInference2.ts(12,52): error TS2345: Argument of type '{ name: string; b: number; }' is not assignable to parameter of type '{ name: string; a: number; }'.
Object literal may only specify known properties, and 'b' does not exist in type '{ name: string; a: number; }'.
==== tests/cases/compiler/typeArgInference2.ts (1 errors) ====
interface Item {
name: string;
}
declare function foo<T extends Item>(x?: T, y?: T): T;
var z1 = foo(null); // any
var z2 = foo(); // Item
var z3 = foo({ name: null }); // { name: any }
var z4 = foo({ name: "abc" }); // { name: string }
var z5 = foo({ name: "abc", a: 5 }); // { name: string; a: number }
var z6 = foo({ name: "abc", a: 5 }, { name: "def", b: 5 }); // error
~~~~
!!! error TS2345: Argument of type '{ name: string; b: number; }' is not assignable to parameter of type '{ name: string; a: number; }'.
!!! error TS2345: Object literal may only specify known properties, and 'b' does not exist in type '{ name: string; a: number; }'.

View file

@ -54,8 +54,8 @@ var z5 = foo({ name: "abc", a: 5 }); // { name: string; a: number }
>5 : 5
var z6 = foo({ name: "abc", a: 5 }, { name: "def", b: 5 }); // error
>z6 : any
>foo({ name: "abc", a: 5 }, { name: "def", b: 5 }) : any
>z6 : { name: string; a: number; b?: undefined; } | { name: string; b: number; a?: undefined; }
>foo({ name: "abc", a: 5 }, { name: "def", b: 5 }) : { name: string; a: number; b?: undefined; } | { name: string; b: number; a?: undefined; }
>foo : <T extends Item>(x?: T, y?: T) => T
>{ name: "abc", a: 5 } : { name: string; a: number; }
>name : string

View file

@ -1,6 +1,5 @@
tests/cases/conformance/expressions/functionCalls/typeArgumentInference.ts(68,29): error TS2345: Argument of type '0' is not assignable to parameter of type '""'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInference.ts(82,69): error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type '{ x: number; z: Date; }'.
Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; z: Date; }'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInference.ts(83,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'a9e' has type '{ x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }' at tests/cases/conformance/expressions/functionCalls/typeArgumentInference.ts 81:4, but here has type '{}'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInference.ts(84,74): error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type 'A92'.
Object literal may only specify known properties, and 'y' does not exist in type 'A92'.
@ -90,10 +89,9 @@ tests/cases/conformance/expressions/functionCalls/typeArgumentInference.ts(84,74
z?: Date;
}
var a9e = someGenerics9(undefined, { x: 6, z: new Date() }, { x: 6, y: '' });
~~~~~
!!! error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type '{ x: number; z: Date; }'.
!!! error TS2345: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; z: Date; }'.
var a9e: {};
~~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'a9e' has type '{ x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }' at tests/cases/conformance/expressions/functionCalls/typeArgumentInference.ts 81:4, but here has type '{}'.
var a9f = someGenerics9<A92>(undefined, { x: 6, z: new Date() }, { x: 6, y: '' });
~~~~~
!!! error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type 'A92'.

View file

@ -421,8 +421,8 @@ interface A92 {
>Date : Date
}
var a9e = someGenerics9(undefined, { x: 6, z: new Date() }, { x: 6, y: '' });
>a9e : any
>someGenerics9(undefined, { x: 6, z: new Date() }, { x: 6, y: '' }) : any
>a9e : { x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }
>someGenerics9(undefined, { x: 6, z: new Date() }, { x: 6, y: '' }) : { x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }
>someGenerics9 : <T>(a: T, b: T, c: T) => T
>undefined : undefined
>{ x: 6, z: new Date() } : { x: number; z: Date; }
@ -438,7 +438,7 @@ var a9e = someGenerics9(undefined, { x: 6, z: new Date() }, { x: 6, y: '' });
>'' : ""
var a9e: {};
>a9e : any
>a9e : { x: number; z: Date; y?: undefined; } | { x: number; y: string; z?: undefined; }
var a9f = someGenerics9<A92>(undefined, { x: 6, z: new Date() }, { x: 6, y: '' });
>a9f : any

View file

@ -12,8 +12,7 @@ tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceConstruct
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceConstructSignatures.ts(106,33): error TS2345: Argument of type '0' is not assignable to parameter of type '""'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceConstructSignatures.ts(118,9): error TS2304: Cannot find name 'Window'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceConstructSignatures.ts(120,51): error TS2304: Cannot find name 'window'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceConstructSignatures.ts(120,69): error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type '{ x: number; z: any; }'.
Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; z: any; }'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceConstructSignatures.ts(121,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'a9e' has type '{ x: number; z: any; y?: undefined; } | { x: number; y: string; z?: undefined; }' at tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceConstructSignatures.ts 119:4, but here has type '{}'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceConstructSignatures.ts(122,56): error TS2304: Cannot find name 'window'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceConstructSignatures.ts(122,74): error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type 'A92'.
Object literal may only specify known properties, and 'y' does not exist in type 'A92'.
@ -162,10 +161,9 @@ tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceConstruct
var a9e = new someGenerics9(undefined, { x: 6, z: window }, { x: 6, y: '' });
~~~~~~
!!! error TS2304: Cannot find name 'window'.
~~~~~
!!! error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type '{ x: number; z: any; }'.
!!! error TS2345: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; z: any; }'.
var a9e: {};
~~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'a9e' has type '{ x: number; z: any; y?: undefined; } | { x: number; y: string; z?: undefined; }' at tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceConstructSignatures.ts 119:4, but here has type '{}'.
var a9f = new someGenerics9<A92>(undefined, { x: 6, z: window }, { x: 6, y: '' });
~~~~~~
!!! error TS2304: Cannot find name 'window'.

View file

@ -524,8 +524,8 @@ interface A92 {
>Window : No type information available!
}
var a9e = new someGenerics9(undefined, { x: 6, z: window }, { x: 6, y: '' });
>a9e : any
>new someGenerics9(undefined, { x: 6, z: window }, { x: 6, y: '' }) : any
>a9e : { x: number; z: any; y?: undefined; } | { x: number; y: string; z?: undefined; }
>new someGenerics9(undefined, { x: 6, z: window }, { x: 6, y: '' }) : { x: number; z: any; y?: undefined; } | { x: number; y: string; z?: undefined; }
>someGenerics9 : someGenerics9
>undefined : undefined
>{ x: 6, z: window } : { x: number; z: any; }
@ -540,7 +540,7 @@ var a9e = new someGenerics9(undefined, { x: 6, z: window }, { x: 6, y: '' });
>'' : ""
var a9e: {};
>a9e : any
>a9e : { x: number; z: any; y?: undefined; } | { x: number; y: string; z?: undefined; }
var a9f = new someGenerics9<A92>(undefined, { x: 6, z: window }, { x: 6, y: '' });
>a9f : any

View file

@ -17,8 +17,7 @@ tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConst
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(73,29): error TS2345: Argument of type '0' is not assignable to parameter of type '""'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(85,9): error TS2304: Cannot find name 'Window'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(87,47): error TS2304: Cannot find name 'window'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(87,65): error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type '{ x: number; z: any; }'.
Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; z: any; }'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(88,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'a9e' has type '{ x: number; z: any; y?: undefined; } | { x: number; y: string; z?: undefined; }' at tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts 86:4, but here has type '{}'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(89,52): error TS2304: Cannot find name 'window'.
tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts(89,70): error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type 'A92'.
Object literal may only specify known properties, and 'y' does not exist in type 'A92'.
@ -144,10 +143,9 @@ tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConst
var a9e = someGenerics9(undefined, { x: 6, z: window }, { x: 6, y: '' });
~~~~~~
!!! error TS2304: Cannot find name 'window'.
~~~~~
!!! error TS2345: Argument of type '{ x: number; y: string; }' is not assignable to parameter of type '{ x: number; z: any; }'.
!!! error TS2345: Object literal may only specify known properties, and 'y' does not exist in type '{ x: number; z: any; }'.
var a9e: {};
~~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'a9e' has type '{ x: number; z: any; y?: undefined; } | { x: number; y: string; z?: undefined; }' at tests/cases/conformance/expressions/functionCalls/typeArgumentInferenceWithConstraints.ts 86:4, but here has type '{}'.
var a9f = someGenerics9<A92>(undefined, { x: 6, z: window }, { x: 6, y: '' });
~~~~~~
!!! error TS2304: Cannot find name 'window'.

View file

@ -464,8 +464,8 @@ interface A92 {
>Window : No type information available!
}
var a9e = someGenerics9(undefined, { x: 6, z: window }, { x: 6, y: '' });
>a9e : any
>someGenerics9(undefined, { x: 6, z: window }, { x: 6, y: '' }) : any
>a9e : { x: number; z: any; y?: undefined; } | { x: number; y: string; z?: undefined; }
>someGenerics9(undefined, { x: 6, z: window }, { x: 6, y: '' }) : { x: number; z: any; y?: undefined; } | { x: number; y: string; z?: undefined; }
>someGenerics9 : <T extends any>(a: T, b: T, c: T) => T
>undefined : undefined
>{ x: 6, z: window } : { x: number; z: any; }
@ -480,7 +480,7 @@ var a9e = someGenerics9(undefined, { x: 6, z: window }, { x: 6, y: '' });
>'' : ""
var a9e: {};
>a9e : any
>a9e : { x: number; z: any; y?: undefined; } | { x: number; y: string; z?: undefined; }
var a9f = someGenerics9<A92>(undefined, { x: 6, z: window }, { x: 6, y: '' });
>a9f : any

View file

@ -0,0 +1,52 @@
// @strict: true
// @declaration: true
// Object literals in unions are normalized upon widening
let a1 = [{ a: 0 }, { a: 1, b: "x" }, { a: 2, b: "y", c: true }][0];
a1.a; // number
a1.b; // string | undefined
a1.c; // boolean | undefined
a1 = { a: 1 };
a1 = { a: 0, b: 0 }; // Error
a1 = { b: "y" }; // Error
a1 = { c: true }; // Error
let a2 = [{ a: 1, b: 2 }, { a: "abc" }, {}][0];
a2.a; // string | number | undefined
a2.b; // number | undefined
a2 = { a: 10, b: 20 };
a2 = { a: "def" };
a2 = {};
a2 = { a: "def", b: 20 }; // Error
a2 = { a: 1 }; // Error
// Object literals containing spreads are not normalized
declare let b1: { a: string, b: string } | { b: string, c: string };
let b2 = { ...b1, z: 55 };
let b3 = { ...b2 };
// Before widening {} acts like { [x: string]: undefined }, which is a
// subtype of types with all optional properties
declare let opts: { foo?: string, bar?: string, baz?: boolean };
let c1 = !true ? {} : opts;
let c2 = !true ? opts : {};
let c3 = !true ? { a: 0, b: 0 } : {};
let c4 = !true ? {} : { a: 0, b: 0 };
// Normalization applies to nested properties
let d1 = [{ kind: 'a', pos: { x: 0, y: 0 } }, { kind: 'b', pos: !true ? { a: "x" } : { b: 0 } }][0];
d1.kind;
d1.pos;
d1.pos.x;
d1.pos.y;
d1.pos.a;
d1.pos.b;
declare function f<T>(...items: T[]): T;
declare let data: { a: 1, b: "abc", c: true };
// Object literals are inferred as a single normalized union type
let e1 = f({ a: 1, b: 2 }, { a: "abc" }, {});
let e2 = f({}, { a: "abc" }, { a: 1, b: 2 });
let e3 = f(data, { a: 2 });
let e4 = f({ a: 2 }, data);