Reduce intersections by discriminants (#36696)

* Treat never-like intersections as never

* Accept new baselines

* Fix compiler issues revealed by increased intersection correctness

* Delete fourslash tests that are no longer applicable

* Include isNeverLikeIntersection check in getNormalizedType

* Erase never-like types in several more places

* Check that base types are not never-like

* Add comments

* Revert isNeverLikeType check in getIndexType (keyof shouldn't resolve member types)

* Introduce getReducedType for union and intersection types

* Don't reduce in getApparentType

* Avoid relationship check in resolveMappedTypeMembers

* Accept new baselines

* Don't call getReducedType in getIndexType

* Ensure reduced and unreduced forms of a type can compare identical

* Reduce types before converting them to string representation

* Accept new baselines

* Reduce intersections before obtaining keyof X

* Add tests

* Accept new baselines

* Fix comment in tests

* Don't infer from empty intersection types

* Add tests

* Accept new baselines

* Defer instantiation of mapped type property types

* Accept new baselines

* Include more precise type in diagnostic

* Accept new baselines

* Minor optimization

* Improve error message

* Optional properties in intersections are never discriminants
This commit is contained in:
Anders Hejlsberg
2020-02-28 17:06:44 -08:00
committed by GitHub
parent f31ff2dac0
commit be4b814a4c
32 changed files with 1232 additions and 190 deletions
+113 -37
View File
@@ -4077,6 +4077,8 @@ namespace ts {
return undefined!; // TODO: GH#18217
}
type = getReducedType(type);
if (type.flags & TypeFlags.Any) {
context.approximateLength += 3;
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
@@ -7145,6 +7147,7 @@ namespace ts {
let type: Type | undefined;
if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
if (declaration.dotDotDotToken) {
parentType = getReducedType(parentType);
if (parentType.flags & TypeFlags.Unknown || !isValidSpreadType(parentType)) {
error(declaration, Diagnostics.Rest_types_may_only_be_created_from_object_types);
return errorType;
@@ -8022,13 +8025,17 @@ namespace ts {
}
function getTypeOfSymbol(symbol: Symbol): Type {
if (getCheckFlags(symbol) & CheckFlags.DeferredType) {
const checkFlags = getCheckFlags(symbol);
if (checkFlags & CheckFlags.DeferredType) {
return getTypeOfSymbolWithDeferredType(symbol);
}
if (getCheckFlags(symbol) & CheckFlags.Instantiated) {
if (checkFlags & CheckFlags.Instantiated) {
return getTypeOfInstantiatedSymbol(symbol);
}
if (getCheckFlags(symbol) & CheckFlags.ReverseMapped) {
if (checkFlags & CheckFlags.Mapped) {
return getTypeOfMappedSymbol(symbol as MappedSymbol);
}
if (checkFlags & CheckFlags.ReverseMapped) {
return getTypeOfReverseMappedSymbol(symbol as ReverseMappedSymbol);
}
if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) {
@@ -8329,7 +8336,7 @@ namespace ts {
error(baseTypeNode.expression, Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments);
return type.resolvedBaseTypes = emptyArray;
}
baseType = getReturnTypeOfSignature(constructors[0]);
baseType = getReducedType(getReturnTypeOfSignature(constructors[0]));
}
if (baseType === errorType) {
@@ -8376,8 +8383,8 @@ namespace ts {
}
// TODO: Given that we allow type parmeters here now, is this `!isGenericMappedType(type)` check really needed?
// There's no reason a `T` should be allowed while a `Readonly<T>` should not.
return !!(type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.Any)) && !isGenericMappedType(type) ||
!!(type.flags & TypeFlags.Intersection) && every((<IntersectionType>type).types, isValidBaseType);
return !!(type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.Any) && !isGenericMappedType(type) ||
type.flags & TypeFlags.Intersection && every((<IntersectionType>type).types, isValidBaseType));
}
function resolveBaseTypesOfInterface(type: InterfaceType): void {
@@ -8385,7 +8392,7 @@ namespace ts {
for (const declaration of type.symbol.declarations) {
if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)) {
for (const node of getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)!) {
const baseType = getTypeFromTypeNode(node);
const baseType = getReducedType(getTypeFromTypeNode(node));
if (baseType !== errorType) {
if (isValidBaseType(baseType)) {
if (type !== baseType && !hasBaseType(baseType, type)) {
@@ -9619,7 +9626,6 @@ namespace ts {
// mapped type is itself an instantiated type, combine the iteration mapper with the
// instantiation mapper.
const templateMapper = combineTypeMappers(type.mapper, createTypeMapper([typeParameter], [t]));
const propType = instantiateType(templateType, templateMapper);
// If the current iteration type constituent is a string literal type, create a property.
// Otherwise, for type string create a string index signature.
if (isTypeUsableAsPropertyName(t)) {
@@ -9629,13 +9635,11 @@ namespace ts {
!(templateModifiers & MappedTypeModifiers.ExcludeOptional) && modifiersProp && modifiersProp.flags & SymbolFlags.Optional);
const isReadonly = !!(templateModifiers & MappedTypeModifiers.IncludeReadonly ||
!(templateModifiers & MappedTypeModifiers.ExcludeReadonly) && modifiersProp && isReadonlySymbol(modifiersProp));
const prop = createSymbol(SymbolFlags.Property | (isOptional ? SymbolFlags.Optional : 0), propName, isReadonly ? CheckFlags.Readonly : 0);
// When creating an optional property in strictNullChecks mode, if 'undefined' isn't assignable to the
// type, we include 'undefined' in the type. Similarly, when creating a non-optional property in strictNullChecks
// mode, if the underlying property is optional we remove 'undefined' from the type.
prop.type = strictNullChecks && isOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType) :
strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) :
propType;
const stripOptional = strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional;
const prop = <MappedSymbol>createSymbol(SymbolFlags.Property | (isOptional ? SymbolFlags.Optional : 0), propName,
CheckFlags.Mapped | (isReadonly ? CheckFlags.Readonly : 0) | (stripOptional ? CheckFlags.StripOptional : 0));
prop.mappedType = type;
prop.mapper = templateMapper;
if (modifiersProp) {
prop.syntheticOrigin = modifiersProp;
prop.declarations = modifiersProp.declarations;
@@ -9643,16 +9647,41 @@ namespace ts {
prop.nameType = t;
members.set(propName, prop);
}
else if (t.flags & (TypeFlags.Any | TypeFlags.String)) {
stringIndexInfo = createIndexInfo(propType, !!(templateModifiers & MappedTypeModifiers.IncludeReadonly));
}
else if (t.flags & (TypeFlags.Number | TypeFlags.Enum)) {
numberIndexInfo = createIndexInfo(numberIndexInfo ? getUnionType([numberIndexInfo.type, propType]) : propType,
!!(templateModifiers & MappedTypeModifiers.IncludeReadonly));
else if (t.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number | TypeFlags.Enum)) {
const propType = instantiateType(templateType, templateMapper);
if (t.flags & (TypeFlags.Any | TypeFlags.String)) {
stringIndexInfo = createIndexInfo(propType, !!(templateModifiers & MappedTypeModifiers.IncludeReadonly));
}
else {
numberIndexInfo = createIndexInfo(numberIndexInfo ? getUnionType([numberIndexInfo.type, propType]) : propType,
!!(templateModifiers & MappedTypeModifiers.IncludeReadonly));
}
}
}
}
function getTypeOfMappedSymbol(symbol: MappedSymbol) {
if (!symbol.type) {
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
return errorType;
}
const templateType = getTemplateTypeFromMappedType(<MappedType>symbol.mappedType.target || symbol.mappedType);
const propType = instantiateType(templateType, symbol.mapper);
// When creating an optional property in strictNullChecks mode, if 'undefined' isn't assignable to the
// type, we include 'undefined' in the type. Similarly, when creating a non-optional property in strictNullChecks
// mode, if the underlying property is optional we remove 'undefined' from the type.
let type = strictNullChecks && symbol.flags & SymbolFlags.Optional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType) :
symbol.checkFlags & CheckFlags.StripOptional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) :
propType;
if (!popTypeResolution()) {
error(currentNode, Diagnostics.Type_of_property_0_circularly_references_itself_in_mapped_type_1, symbolToString(symbol), typeToString(symbol.mappedType));
type = errorType;
}
symbol.type = type;
}
return symbol.type;
}
function getTypeParameterFromMappedType(type: MappedType) {
return type.typeParameter ||
(type.typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(type.declaration.typeParameter)));
@@ -9800,7 +9829,7 @@ namespace ts {
}
function getPropertiesOfType(type: Type): Symbol[] {
type = getApparentType(type);
type = getApparentType(getReducedType(type));
return type.flags & TypeFlags.UnionOrIntersection ?
getPropertiesOfUnionOrIntersectionType(<UnionType>type) :
getPropertiesOfObjectType(type);
@@ -10141,7 +10170,7 @@ namespace ts {
/**
* 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
* type itself. Note that the apparent type of a union type is the union type itself.
* type itself.
*/
function getApparentType(type: Type): Type {
const t = type.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(type) || unknownType : type;
@@ -10169,7 +10198,7 @@ namespace ts {
let checkFlags = 0;
for (const current of containingType.types) {
const type = getApparentType(current);
if (type !== errorType) {
if (!(type === errorType || type.flags & TypeFlags.Never)) {
const prop = getPropertyOfType(type, name);
const modifiers = prop ? getDeclarationModifierFlagsFromSymbol(prop) : 0;
if (prop && !(modifiers & excludeModifiers)) {
@@ -10240,6 +10269,9 @@ namespace ts {
if (isLiteralType(type)) {
checkFlags |= CheckFlags.HasLiteralType;
}
if (type.flags & TypeFlags.Never) {
checkFlags |= CheckFlags.HasNeverType;
}
propTypes.push(type);
}
addRange(propTypes, indexTypes);
@@ -10291,6 +10323,44 @@ namespace ts {
return property && !(getCheckFlags(property) & CheckFlags.ReadPartial) ? property : undefined;
}
/**
* Return the reduced form of the given type. For a union type, it is a union of the normalized constituent types.
* For an intersection of types containing one or more mututally exclusive discriminant properties, it is 'never'.
* For all other types, it is simply the type itself. Discriminant properties are considered mutually exclusive when
* no constituent property has type 'never', but the intersection of the constituent property types is 'never'.
*/
function getReducedType(type: Type): Type {
if (type.flags & TypeFlags.Union && (<UnionType>type).objectFlags & ObjectFlags.ContainsIntersections) {
return (<UnionType>type).resolvedReducedType || ((<UnionType>type).resolvedReducedType = getReducedUnionType(<UnionType>type));
}
else if (type.flags & TypeFlags.Intersection) {
if (!((<IntersectionType>type).objectFlags & ObjectFlags.IsNeverIntersectionComputed)) {
(<IntersectionType>type).objectFlags |= ObjectFlags.IsNeverIntersectionComputed |
(some(getPropertiesOfUnionOrIntersectionType(<IntersectionType>type), isDiscriminantWithNeverType) ? ObjectFlags.IsNeverIntersection : 0);
}
return (<IntersectionType>type).objectFlags & ObjectFlags.IsNeverIntersection ? neverType : type;
}
return type;
}
function getReducedUnionType(unionType: UnionType) {
const reducedTypes = sameMap(unionType.types, getReducedType);
if (reducedTypes === unionType.types) {
return unionType;
}
const reduced = getUnionType(reducedTypes);
if (reduced.flags & TypeFlags.Union) {
(<UnionType>reduced).resolvedReducedType = reduced;
}
return reduced;
}
function isDiscriminantWithNeverType(prop: Symbol) {
return !(prop.flags & SymbolFlags.Optional) &&
(getCheckFlags(prop) & (CheckFlags.Discriminant | CheckFlags.HasNeverType)) === CheckFlags.Discriminant &&
!!(getTypeOfSymbol(prop).flags & TypeFlags.Never);
}
/**
* Return the symbol for the property with the given name in the given type. Creates synthetic union properties when
* necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from
@@ -10300,7 +10370,7 @@ namespace ts {
* @param name a name of property to look up in a given type
*/
function getPropertyOfType(type: Type, name: __String): Symbol | undefined {
type = getApparentType(type);
type = getApparentType(getReducedType(type));
if (type.flags & TypeFlags.Object) {
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
const symbol = resolved.members.get(name);
@@ -10338,7 +10408,7 @@ namespace ts {
* maps primitive types and type parameters are to their apparent types.
*/
function getSignaturesOfType(type: Type, kind: SignatureKind): readonly Signature[] {
return getSignaturesOfStructuredType(getApparentType(type), kind);
return getSignaturesOfStructuredType(getApparentType(getReducedType(type)), kind);
}
function getIndexInfoOfStructuredType(type: Type, kind: IndexKind): IndexInfo | undefined {
@@ -10356,13 +10426,13 @@ namespace ts {
// Return the indexing info of the given kind in the given type. Creates synthetic union index types when necessary and
// maps primitive types and type parameters are to their apparent types.
function getIndexInfoOfType(type: Type, kind: IndexKind): IndexInfo | undefined {
return getIndexInfoOfStructuredType(getApparentType(type), kind);
return getIndexInfoOfStructuredType(getApparentType(getReducedType(type)), kind);
}
// Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and
// maps primitive types and type parameters are to their apparent types.
function getIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined {
return getIndexTypeOfStructuredType(getApparentType(type), kind);
return getIndexTypeOfStructuredType(getApparentType(getReducedType(type)), kind);
}
function getImplicitIndexTypeOfType(type: Type, kind: IndexKind): Type | undefined {
@@ -11932,7 +12002,9 @@ namespace ts {
neverType;
}
}
return getUnionTypeFromSortedList(typeSet, includes & TypeFlags.NotPrimitiveUnion ? 0 : ObjectFlags.PrimitiveUnion, aliasSymbol, aliasTypeArguments);
const objectFlags = (includes & TypeFlags.NotPrimitiveUnion ? 0 : ObjectFlags.PrimitiveUnion) |
(includes & TypeFlags.Intersection ? ObjectFlags.ContainsIntersections : 0);
return getUnionTypeFromSortedList(typeSet, objectFlags, aliasSymbol, aliasTypeArguments);
}
function getUnionTypePredicate(signatures: readonly Signature[]): TypePredicate | undefined {
@@ -12300,6 +12372,7 @@ namespace ts {
}
function getIndexType(type: Type, stringsOnly = keyofStringsOnly, noIndexSignatures?: boolean): Type {
type = getReducedType(type);
return type.flags & TypeFlags.Union ? getIntersectionType(map((<IntersectionType>type).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) :
type.flags & TypeFlags.Intersection ? getUnionType(map((<IntersectionType>type).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) :
maybeTypeOfKind(type, TypeFlags.InstantiableNonPrimitive) ? getIndexTypeForGenericType(<InstantiableType | UnionOrIntersectionType>type, stringsOnly) :
@@ -12716,7 +12789,7 @@ namespace ts {
// In the following we resolve T[K] to the type of the property in T selected by K.
// We treat boolean as different from other unions to improve errors;
// skipping straight to getPropertyTypeForIndexType gives errors with 'boolean' instead of 'true'.
const apparentObjectType = getApparentType(objectType);
const apparentObjectType = getApparentType(getReducedType(objectType));
if (indexType.flags & TypeFlags.Union && !(indexType.flags & TypeFlags.Boolean)) {
const propTypes: Type[] = [];
let wasMissingProp = false;
@@ -13697,7 +13770,7 @@ namespace ts {
if (typeVariable) {
const mappedTypeVariable = instantiateType(typeVariable, mapper);
if (typeVariable !== mappedTypeVariable) {
return mapType(mappedTypeVariable, t => {
return mapType(getReducedType(mappedTypeVariable), t => {
if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && t !== errorType) {
const replacementMapper = createReplacementMapper(typeVariable, t, mapper);
return isArrayType(t) ? instantiateMappedArrayType(t, type, replacementMapper) :
@@ -14849,7 +14922,8 @@ namespace ts {
}
}
else {
if (!(source.flags === target.flags && source.flags & TypeFlags.Substructure)) return false;
if (!(source.flags & TypeFlags.UnionOrIntersection) && !(target.flags & TypeFlags.UnionOrIntersection) &&
source.flags !== target.flags && !(source.flags & TypeFlags.Substructure)) return false;
}
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) {
const related = relation.get(getRelationKey(source, target, IntersectionState.None, relation));
@@ -14868,15 +14942,16 @@ namespace ts {
}
function getNormalizedType(type: Type, writing: boolean): Type {
do {
while (true) {
const t = isFreshLiteralType(type) ? (<FreshableType>type).regularType :
getObjectFlags(type) & ObjectFlags.Reference && (<TypeReference>type).node ? createTypeReference((<TypeReference>type).target, getTypeArguments(<TypeReference>type)) :
type.flags & TypeFlags.UnionOrIntersection ? getReducedType(type) :
type.flags & TypeFlags.Substitution ? writing ? (<SubstitutionType>type).typeVariable : (<SubstitutionType>type).substitute :
type.flags & TypeFlags.Simplifiable ? getSimplifiedType(type, writing) :
type;
if (t === type) break;
type = t;
} while (true);
}
return type;
}
@@ -18164,6 +18239,7 @@ namespace ts {
}
}
else {
source = getReducedType(source);
if (!(priority & InferencePriority.NoConstraints && source.flags & (TypeFlags.Intersection | TypeFlags.Instantiable))) {
const apparentSource = getApparentType(source);
// getApparentType can return _any_ type, since an indexed access or conditional may simplify to any other type.
@@ -22584,7 +22660,7 @@ namespace ts {
hasComputedStringProperty = false;
hasComputedNumberProperty = false;
}
const type = checkExpression(memberDecl.expression);
const type = getReducedType(checkExpression(memberDecl.expression));
if (!isValidSpreadType(type)) {
error(memberDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types);
return errorType;
@@ -22792,7 +22868,7 @@ namespace ts {
spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, objectFlags, /*readonly*/ false);
attributesTable = createSymbolTable();
}
const exprType = checkExpressionCached(attributeDecl.expression, checkMode);
const exprType = getReducedType(checkExpressionCached(attributeDecl.expression, checkMode));
if (isTypeAny(exprType)) {
hasSpreadAnyType = true;
}
@@ -32676,7 +32752,7 @@ namespace ts {
}
checkTypeReferenceNode(typeRefNode);
if (produceDiagnostics) {
const t = getTypeFromTypeNode(typeRefNode);
const t = getReducedType(getTypeFromTypeNode(typeRefNode));
if (t !== errorType) {
if (isValidBaseType(t)) {
const genericDiag = t.symbol && t.symbol.flags & SymbolFlags.Class ?
+4
View File
@@ -2365,6 +2365,10 @@
"category": "Error",
"code": 2614
},
"Type of property '{0}' circularly references itself in mapped type '{1}'.": {
"category": "Error",
"code": 2615
},
"Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": {
"category": "Error",
+1 -3
View File
@@ -1795,9 +1795,7 @@ namespace ts {
const target = getTargetOfBindingOrAssignmentElement(bindingElement);
if (target && isPropertyName(target)) {
return isComputedPropertyName(target) && isStringOrNumericLiteral(target.expression)
? target.expression
: target;
return target;
}
}
+1 -1
View File
@@ -976,7 +976,7 @@ namespace ts {
);
}
function visitArrayAssignmentTarget(node: AssignmentPattern) {
function visitArrayAssignmentTarget(node: BindingOrAssignmentElement) {
const target = getTargetOfBindingOrAssignmentElement(node);
if (target && isPrivateIdentifierPropertyAccessExpression(target)) {
const wrapped = wrapPrivateIdentifierForDestructuringTarget(target);
+21 -4
View File
@@ -4155,6 +4155,9 @@ namespace ts {
OptionalParameter = 1 << 14, // Optional parameter
RestParameter = 1 << 15, // Rest parameter
DeferredType = 1 << 16, // Calculation of the type of this symbol is deferred due to processing costs, should be fetched with `getTypeOfSymbolWithDeferredType`
HasNeverType = 1 << 17, // Synthetic property with at least one never type in constituents
Mapped = 1 << 18, // Property of mapped type
StripOptional = 1 << 19, // Strip optionality in mapped property
Synthetic = SyntheticProperty | SyntheticMethod,
Discriminant = HasNonUniformType | HasLiteralType,
Partial = ReadPartial | WritePartial
@@ -4165,6 +4168,12 @@ namespace ts {
checkFlags: CheckFlags;
}
/* @internal */
export interface MappedSymbol extends TransientSymbol {
mappedType: MappedType;
mapper: TypeMapper;
}
/* @internal */
export interface ReverseMappedSymbol extends TransientSymbol {
propertyType: Type;
@@ -4362,16 +4371,16 @@ namespace ts {
NotPrimitiveUnion = Any | Unknown | Enum | Void | Never | StructuredOrInstantiable,
// The following flags are aggregated during union and intersection type construction
/* @internal */
IncludesMask = Any | Unknown | Primitive | Never | Object | Union | NonPrimitive,
IncludesMask = Any | Unknown | Primitive | Never | Object | Union | Intersection | NonPrimitive,
// The following flags are used for different purposes during union and intersection type construction
/* @internal */
IncludesStructuredOrInstantiable = TypeParameter,
/* @internal */
IncludesNonWideningType = Intersection,
IncludesNonWideningType = Index,
/* @internal */
IncludesWildcard = Index,
IncludesWildcard = IndexedAccess,
/* @internal */
IncludesEmptyObject = IndexedAccess,
IncludesEmptyObject = Conditional,
}
export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;
@@ -4487,6 +4496,12 @@ namespace ts {
CouldContainTypeVariablesComputed = 1 << 26, // CouldContainTypeVariables flag has been computed
/* @internal */
CouldContainTypeVariables = 1 << 27, // Type could contain a type variable
/* @internal */
ContainsIntersections = 1 << 28, // Union contains intersections
/* @internal */
IsNeverIntersectionComputed = 1 << 28, // IsNeverLike flag has been computed
/* @internal */
IsNeverIntersection = 1 << 29, // Intersection reduces to never
ClassOrInterface = Class | Interface,
/* @internal */
RequiresWidening = ContainsWideningType | ContainsObjectOrArrayLiteral,
@@ -4608,6 +4623,8 @@ namespace ts {
}
export interface UnionType extends UnionOrIntersectionType {
/* @internal */
resolvedReducedType: Type;
}
export interface IntersectionType extends UnionOrIntersectionType {
@@ -2,10 +2,9 @@ tests/cases/conformance/types/union/discriminatedUnionTypes2.ts(27,30): error TS
Object literal may only specify known properties, and 'c' does not exist in type '{ a: null; b: string; }'.
tests/cases/conformance/types/union/discriminatedUnionTypes2.ts(32,11): error TS2339: Property 'b' does not exist on type '{ a: 0; b: string; } | { a: T; c: number; }'.
Property 'b' does not exist on type '{ a: T; c: number; }'.
tests/cases/conformance/types/union/discriminatedUnionTypes2.ts(132,11): error TS2339: Property 'value' does not exist on type 'never'.
==== tests/cases/conformance/types/union/discriminatedUnionTypes2.ts (3 errors) ====
==== tests/cases/conformance/types/union/discriminatedUnionTypes2.ts (2 errors) ====
function f10(x : { kind: false, a: string } | { kind: true, b: string } | { kind: string, c: string }) {
if (x.kind === false) {
x.a;
@@ -143,9 +142,7 @@ tests/cases/conformance/types/union/discriminatedUnionTypes2.ts(132,11): error T
x.value; // number
}
else {
x.value; // Error, x is never
~~~~~
!!! error TS2339: Property 'value' does not exist on type 'never'.
x.value; // number
}
}
@@ -130,7 +130,7 @@ function foo1(x: RuntimeValue & { type: 'number' }) {
x.value; // number
}
else {
x.value; // Error, x is never
x.value; // number
}
}
@@ -226,7 +226,7 @@ function foo1(x) {
x.value; // number
}
else {
x.value; // Error, x is never
x.value; // number
}
}
function foo2(x) {
@@ -317,9 +317,9 @@ function f(problem: abc & (b | c)) {
>c : Symbol(c, Decl(discriminatedUnionTypes2.ts, 104, 1))
if (problem.type === 'b') {
>problem.type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 101, 10), Decl(discriminatedUnionTypes2.ts, 105, 10), Decl(discriminatedUnionTypes2.ts, 97, 10), Decl(discriminatedUnionTypes2.ts, 101, 10), Decl(discriminatedUnionTypes2.ts, 97, 10) ... and 5 more)
>problem.type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 101, 10), Decl(discriminatedUnionTypes2.ts, 105, 10))
>problem : Symbol(problem, Decl(discriminatedUnionTypes2.ts, 112, 11))
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 101, 10), Decl(discriminatedUnionTypes2.ts, 105, 10), Decl(discriminatedUnionTypes2.ts, 97, 10), Decl(discriminatedUnionTypes2.ts, 101, 10), Decl(discriminatedUnionTypes2.ts, 97, 10) ... and 5 more)
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 101, 10), Decl(discriminatedUnionTypes2.ts, 105, 10))
problem.name;
>problem.name : Symbol(name, Decl(discriminatedUnionTypes2.ts, 102, 14))
@@ -356,9 +356,9 @@ function foo1(x: RuntimeValue & { type: 'number' }) {
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 126, 33))
if (x.type === 'number') {
>x.type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 126, 33), Decl(discriminatedUnionTypes2.ts, 123, 7), Decl(discriminatedUnionTypes2.ts, 126, 33), Decl(discriminatedUnionTypes2.ts, 124, 7) ... and 1 more)
>x.type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 126, 33))
>x : Symbol(x, Decl(discriminatedUnionTypes2.ts, 126, 14))
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 126, 33), Decl(discriminatedUnionTypes2.ts, 123, 7), Decl(discriminatedUnionTypes2.ts, 126, 33), Decl(discriminatedUnionTypes2.ts, 124, 7) ... and 1 more)
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 126, 33))
x.value; // number
>x.value : Symbol(value, Decl(discriminatedUnionTypes2.ts, 122, 23))
@@ -366,8 +366,10 @@ function foo1(x: RuntimeValue & { type: 'number' }) {
>value : Symbol(value, Decl(discriminatedUnionTypes2.ts, 122, 23))
}
else {
x.value; // Error, x is never
x.value; // number
>x.value : Symbol(value, Decl(discriminatedUnionTypes2.ts, 122, 23))
>x : Symbol(x, Decl(discriminatedUnionTypes2.ts, 126, 14))
>value : Symbol(value, Decl(discriminatedUnionTypes2.ts, 122, 23))
}
}
@@ -379,9 +381,9 @@ function foo2(x: RuntimeValue & ({ type: 'number' } | { type: 'string' })) {
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 135, 55))
if (x.type === 'number') {
>x.type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 135, 34), Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 135, 55), Decl(discriminatedUnionTypes2.ts, 123, 7) ... and 7 more)
>x.type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 135, 34), Decl(discriminatedUnionTypes2.ts, 123, 7), Decl(discriminatedUnionTypes2.ts, 135, 55))
>x : Symbol(x, Decl(discriminatedUnionTypes2.ts, 135, 14))
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 135, 34), Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 135, 55), Decl(discriminatedUnionTypes2.ts, 123, 7) ... and 7 more)
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 135, 34), Decl(discriminatedUnionTypes2.ts, 123, 7), Decl(discriminatedUnionTypes2.ts, 135, 55))
x.value; // number
>x.value : Symbol(value, Decl(discriminatedUnionTypes2.ts, 122, 23))
@@ -323,13 +323,13 @@ type abc = a | b | c;
>abc : abc
function f(problem: abc & (b | c)) {
>f : (problem: b | c | (a & b) | (a & c) | (b & c) | (c & b)) => void
>problem : b | c | (a & b) | (a & c) | (b & c) | (c & b)
>f : (problem: b | c) => void
>problem : b | c
if (problem.type === 'b') {
>problem.type === 'b' : boolean
>problem.type : "b" | "c"
>problem : b | c | (a & b) | (a & c) | (b & c) | (c & b)
>problem : b | c
>type : "b" | "c"
>'b' : "b"
@@ -362,14 +362,14 @@ type RuntimeValue =
>value : boolean
function foo1(x: RuntimeValue & { type: 'number' }) {
>foo1 : (x: ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "number"; }) | ({ type: "boolean"; value: boolean; } & { type: "number"; })) => void
>x : ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "number"; }) | ({ type: "boolean"; value: boolean; } & { type: "number"; })
>foo1 : (x: { type: "number"; value: number; } & { type: "number"; }) => void
>x : { type: "number"; value: number; } & { type: "number"; }
>type : "number"
if (x.type === 'number') {
>x.type === 'number' : boolean
>x.type : "number"
>x : ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "number"; }) | ({ type: "boolean"; value: boolean; } & { type: "number"; })
>x : { type: "number"; value: number; } & { type: "number"; }
>type : "number"
>'number' : "number"
@@ -379,23 +379,23 @@ function foo1(x: RuntimeValue & { type: 'number' }) {
>value : number
}
else {
x.value; // Error, x is never
>x.value : any
>x : never
>value : any
x.value; // number
>x.value : number
>x : { type: "number"; value: number; } & { type: "number"; }
>value : number
}
}
function foo2(x: RuntimeValue & ({ type: 'number' } | { type: 'string' })) {
>foo2 : (x: ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "number"; value: number; } & { type: "string"; }) | ({ type: "string"; value: string; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "string"; }) | ({ type: "boolean"; value: boolean; } & { type: "number"; }) | ({ type: "boolean"; value: boolean; } & { type: "string"; })) => void
>x : ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "number"; value: number; } & { type: "string"; }) | ({ type: "string"; value: string; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "string"; }) | ({ type: "boolean"; value: boolean; } & { type: "number"; }) | ({ type: "boolean"; value: boolean; } & { type: "string"; })
>foo2 : (x: ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "string"; })) => void
>x : ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "string"; })
>type : "number"
>type : "string"
if (x.type === 'number') {
>x.type === 'number' : boolean
>x.type : "string" | "number"
>x : ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "number"; value: number; } & { type: "string"; }) | ({ type: "string"; value: string; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "string"; }) | ({ type: "boolean"; value: boolean; } & { type: "number"; }) | ({ type: "boolean"; value: boolean; } & { type: "string"; })
>x : ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "string"; })
>type : "string" | "number"
>'number' : "number"
@@ -1,8 +1,9 @@
tests/cases/conformance/types/intersection/intersectionReduction.ts(40,1): error TS2322: Type 'any' is not assignable to type 'never'.
tests/cases/conformance/types/intersection/intersectionReduction.ts(41,1): error TS2322: Type 'any' is not assignable to type 'never'.
tests/cases/conformance/types/intersection/intersectionReduction.ts(38,4): error TS2339: Property 'kind' does not exist on type 'never'.
tests/cases/conformance/types/intersection/intersectionReduction.ts(80,1): error TS2322: Type 'any' is not assignable to type 'never'.
tests/cases/conformance/types/intersection/intersectionReduction.ts(81,1): error TS2322: Type 'any' is not assignable to type 'never'.
==== tests/cases/conformance/types/intersection/intersectionReduction.ts (2 errors) ====
==== tests/cases/conformance/types/intersection/intersectionReduction.ts (3 errors) ====
declare const sym1: unique symbol;
declare const sym2: unique symbol;
@@ -35,6 +36,48 @@ tests/cases/conformance/types/intersection/intersectionReduction.ts(41,1): error
type X6 = X | symbol & string;
type X7 = X | void & string;
type A = { kind: 'a', foo: string };
type B = { kind: 'b', foo: number };
type C = { kind: 'c', foo: number };
declare let ab: A & B;
ab.kind; // Error
~~~~
!!! error TS2339: Property 'kind' does not exist on type 'never'.
declare let x: A | (B & C); // A
let a: A = x;
type AB = A & B; // never
type BC = B & C; // never
type U1 = Partial<A & B>; // never
type U2 = Readonly<A & B>; // never
type U3 = (A & B)['kind']; // never
type U4 = A & B | B & C; // never
type U5 = A | B & C; // A
type K1 = keyof (A & B); // string | number | symbol
type K2 = keyof A | keyof B; // 'kind' | 'foo'
type Merge1<T, U> = { [P in keyof (T & U)]: P extends keyof T ? T[P] : U[P & keyof U] }
type Merge2<T, U> = { [P in keyof T | keyof U]: P extends keyof T ? T[P] : U[P & keyof U] }
type M1 = { a: 1, b: 2 } & { a: 2, c: 3 }; // never
type M2 = Merge1<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // {}
type M3 = Merge2<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // { a: 1, b: 2, c: 3 }
type D = { kind: 'd', foo: unknown };
type E = { kind: 'e', foo: unknown };
declare function f10<T>(x: { foo: T }): T;
declare let a1: A | D;
declare let a2: A | D & E;
let r1 = f10(a1); // unknown
let r2 = f10(a2); // string
// Repro from #31663
const x1 = { a: 'foo', b: 42 };
@@ -63,4 +106,16 @@ tests/cases/conformance/types/intersection/intersectionReduction.ts(41,1): error
t1 = t2;
t2 = t1;
// Repro from #36736
const f1 = (t: "a" | ("b" & "c")): "a" => t;
type Container<Type extends string> = {
type: Type;
}
const f2 = (t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a"> => t;
const f3 = (t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t;
const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t;
@@ -31,6 +31,46 @@ type X5 = X | number & object;
type X6 = X | symbol & string;
type X7 = X | void & string;
type A = { kind: 'a', foo: string };
type B = { kind: 'b', foo: number };
type C = { kind: 'c', foo: number };
declare let ab: A & B;
ab.kind; // Error
declare let x: A | (B & C); // A
let a: A = x;
type AB = A & B; // never
type BC = B & C; // never
type U1 = Partial<A & B>; // never
type U2 = Readonly<A & B>; // never
type U3 = (A & B)['kind']; // never
type U4 = A & B | B & C; // never
type U5 = A | B & C; // A
type K1 = keyof (A & B); // string | number | symbol
type K2 = keyof A | keyof B; // 'kind' | 'foo'
type Merge1<T, U> = { [P in keyof (T & U)]: P extends keyof T ? T[P] : U[P & keyof U] }
type Merge2<T, U> = { [P in keyof T | keyof U]: P extends keyof T ? T[P] : U[P & keyof U] }
type M1 = { a: 1, b: 2 } & { a: 2, c: 3 }; // never
type M2 = Merge1<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // {}
type M3 = Merge2<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // { a: 1, b: 2, c: 3 }
type D = { kind: 'd', foo: unknown };
type E = { kind: 'e', foo: unknown };
declare function f10<T>(x: { foo: T }): T;
declare let a1: A | D;
declare let a2: A | D & E;
let r1 = f10(a1); // unknown
let r2 = f10(a2); // string
// Repro from #31663
const x1 = { a: 'foo', b: 42 };
@@ -55,9 +95,25 @@ s2 = s1;
t1 = t2;
t2 = t1;
// Repro from #36736
const f1 = (t: "a" | ("b" & "c")): "a" => t;
type Container<Type extends string> = {
type: Type;
}
const f2 = (t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a"> => t;
const f3 = (t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t;
const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t;
//// [intersectionReduction.js]
ab.kind; // Error
var a = x;
var r1 = f10(a1); // unknown
var r2 = f10(a2); // string
// Repro from #31663
var x1 = { a: 'foo', b: 42 };
var x2 = { a: 'foo', b: true };
@@ -67,3 +123,8 @@ s1 = s2;
s2 = s1;
t1 = t2;
t2 = t1;
// Repro from #36736
var f1 = function (t) { return t; };
var f2 = function (t) { return t; };
var f3 = function (t) { return t; };
var f4 = function (t) { return t; };
@@ -93,64 +93,283 @@ type X7 = X | void & string;
>X7 : Symbol(X7, Decl(intersectionReduction.ts, 29, 30))
>X : Symbol(X, Decl(intersectionReduction.ts, 20, 24))
type A = { kind: 'a', foo: string };
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>kind : Symbol(kind, Decl(intersectionReduction.ts, 32, 10))
>foo : Symbol(foo, Decl(intersectionReduction.ts, 32, 21))
type B = { kind: 'b', foo: number };
>B : Symbol(B, Decl(intersectionReduction.ts, 32, 36))
>kind : Symbol(kind, Decl(intersectionReduction.ts, 33, 10))
>foo : Symbol(foo, Decl(intersectionReduction.ts, 33, 21))
type C = { kind: 'c', foo: number };
>C : Symbol(C, Decl(intersectionReduction.ts, 33, 36))
>kind : Symbol(kind, Decl(intersectionReduction.ts, 34, 10))
>foo : Symbol(foo, Decl(intersectionReduction.ts, 34, 21))
declare let ab: A & B;
>ab : Symbol(ab, Decl(intersectionReduction.ts, 36, 11))
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReduction.ts, 32, 36))
ab.kind; // Error
>ab : Symbol(ab, Decl(intersectionReduction.ts, 36, 11))
declare let x: A | (B & C); // A
>x : Symbol(x, Decl(intersectionReduction.ts, 39, 11))
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReduction.ts, 32, 36))
>C : Symbol(C, Decl(intersectionReduction.ts, 33, 36))
let a: A = x;
>a : Symbol(a, Decl(intersectionReduction.ts, 40, 3))
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>x : Symbol(x, Decl(intersectionReduction.ts, 39, 11))
type AB = A & B; // never
>AB : Symbol(AB, Decl(intersectionReduction.ts, 40, 13))
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReduction.ts, 32, 36))
type BC = B & C; // never
>BC : Symbol(BC, Decl(intersectionReduction.ts, 42, 16))
>B : Symbol(B, Decl(intersectionReduction.ts, 32, 36))
>C : Symbol(C, Decl(intersectionReduction.ts, 33, 36))
type U1 = Partial<A & B>; // never
>U1 : Symbol(U1, Decl(intersectionReduction.ts, 43, 16))
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReduction.ts, 32, 36))
type U2 = Readonly<A & B>; // never
>U2 : Symbol(U2, Decl(intersectionReduction.ts, 45, 25))
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReduction.ts, 32, 36))
type U3 = (A & B)['kind']; // never
>U3 : Symbol(U3, Decl(intersectionReduction.ts, 46, 26))
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReduction.ts, 32, 36))
type U4 = A & B | B & C; // never
>U4 : Symbol(U4, Decl(intersectionReduction.ts, 47, 26))
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReduction.ts, 32, 36))
>B : Symbol(B, Decl(intersectionReduction.ts, 32, 36))
>C : Symbol(C, Decl(intersectionReduction.ts, 33, 36))
type U5 = A | B & C; // A
>U5 : Symbol(U5, Decl(intersectionReduction.ts, 48, 24))
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReduction.ts, 32, 36))
>C : Symbol(C, Decl(intersectionReduction.ts, 33, 36))
type K1 = keyof (A & B); // string | number | symbol
>K1 : Symbol(K1, Decl(intersectionReduction.ts, 49, 20))
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReduction.ts, 32, 36))
type K2 = keyof A | keyof B; // 'kind' | 'foo'
>K2 : Symbol(K2, Decl(intersectionReduction.ts, 51, 24))
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReduction.ts, 32, 36))
type Merge1<T, U> = { [P in keyof (T & U)]: P extends keyof T ? T[P] : U[P & keyof U] }
>Merge1 : Symbol(Merge1, Decl(intersectionReduction.ts, 52, 28))
>T : Symbol(T, Decl(intersectionReduction.ts, 54, 12))
>U : Symbol(U, Decl(intersectionReduction.ts, 54, 14))
>P : Symbol(P, Decl(intersectionReduction.ts, 54, 23))
>T : Symbol(T, Decl(intersectionReduction.ts, 54, 12))
>U : Symbol(U, Decl(intersectionReduction.ts, 54, 14))
>P : Symbol(P, Decl(intersectionReduction.ts, 54, 23))
>T : Symbol(T, Decl(intersectionReduction.ts, 54, 12))
>T : Symbol(T, Decl(intersectionReduction.ts, 54, 12))
>P : Symbol(P, Decl(intersectionReduction.ts, 54, 23))
>U : Symbol(U, Decl(intersectionReduction.ts, 54, 14))
>P : Symbol(P, Decl(intersectionReduction.ts, 54, 23))
>U : Symbol(U, Decl(intersectionReduction.ts, 54, 14))
type Merge2<T, U> = { [P in keyof T | keyof U]: P extends keyof T ? T[P] : U[P & keyof U] }
>Merge2 : Symbol(Merge2, Decl(intersectionReduction.ts, 54, 87))
>T : Symbol(T, Decl(intersectionReduction.ts, 55, 12))
>U : Symbol(U, Decl(intersectionReduction.ts, 55, 14))
>P : Symbol(P, Decl(intersectionReduction.ts, 55, 23))
>T : Symbol(T, Decl(intersectionReduction.ts, 55, 12))
>U : Symbol(U, Decl(intersectionReduction.ts, 55, 14))
>P : Symbol(P, Decl(intersectionReduction.ts, 55, 23))
>T : Symbol(T, Decl(intersectionReduction.ts, 55, 12))
>T : Symbol(T, Decl(intersectionReduction.ts, 55, 12))
>P : Symbol(P, Decl(intersectionReduction.ts, 55, 23))
>U : Symbol(U, Decl(intersectionReduction.ts, 55, 14))
>P : Symbol(P, Decl(intersectionReduction.ts, 55, 23))
>U : Symbol(U, Decl(intersectionReduction.ts, 55, 14))
type M1 = { a: 1, b: 2 } & { a: 2, c: 3 }; // never
>M1 : Symbol(M1, Decl(intersectionReduction.ts, 55, 91))
>a : Symbol(a, Decl(intersectionReduction.ts, 57, 11))
>b : Symbol(b, Decl(intersectionReduction.ts, 57, 17))
>a : Symbol(a, Decl(intersectionReduction.ts, 57, 28))
>c : Symbol(c, Decl(intersectionReduction.ts, 57, 34))
type M2 = Merge1<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // {}
>M2 : Symbol(M2, Decl(intersectionReduction.ts, 57, 42))
>Merge1 : Symbol(Merge1, Decl(intersectionReduction.ts, 52, 28))
>a : Symbol(a, Decl(intersectionReduction.ts, 58, 18))
>b : Symbol(b, Decl(intersectionReduction.ts, 58, 24))
>a : Symbol(a, Decl(intersectionReduction.ts, 58, 34))
>c : Symbol(c, Decl(intersectionReduction.ts, 58, 40))
type M3 = Merge2<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // { a: 1, b: 2, c: 3 }
>M3 : Symbol(M3, Decl(intersectionReduction.ts, 58, 49))
>Merge2 : Symbol(Merge2, Decl(intersectionReduction.ts, 54, 87))
>a : Symbol(a, Decl(intersectionReduction.ts, 59, 18))
>b : Symbol(b, Decl(intersectionReduction.ts, 59, 24))
>a : Symbol(a, Decl(intersectionReduction.ts, 59, 34))
>c : Symbol(c, Decl(intersectionReduction.ts, 59, 40))
type D = { kind: 'd', foo: unknown };
>D : Symbol(D, Decl(intersectionReduction.ts, 59, 49))
>kind : Symbol(kind, Decl(intersectionReduction.ts, 61, 10))
>foo : Symbol(foo, Decl(intersectionReduction.ts, 61, 21))
type E = { kind: 'e', foo: unknown };
>E : Symbol(E, Decl(intersectionReduction.ts, 61, 37))
>kind : Symbol(kind, Decl(intersectionReduction.ts, 62, 10))
>foo : Symbol(foo, Decl(intersectionReduction.ts, 62, 21))
declare function f10<T>(x: { foo: T }): T;
>f10 : Symbol(f10, Decl(intersectionReduction.ts, 62, 37))
>T : Symbol(T, Decl(intersectionReduction.ts, 64, 21))
>x : Symbol(x, Decl(intersectionReduction.ts, 64, 24))
>foo : Symbol(foo, Decl(intersectionReduction.ts, 64, 28))
>T : Symbol(T, Decl(intersectionReduction.ts, 64, 21))
>T : Symbol(T, Decl(intersectionReduction.ts, 64, 21))
declare let a1: A | D;
>a1 : Symbol(a1, Decl(intersectionReduction.ts, 66, 11))
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>D : Symbol(D, Decl(intersectionReduction.ts, 59, 49))
declare let a2: A | D & E;
>a2 : Symbol(a2, Decl(intersectionReduction.ts, 67, 11))
>A : Symbol(A, Decl(intersectionReduction.ts, 30, 28))
>D : Symbol(D, Decl(intersectionReduction.ts, 59, 49))
>E : Symbol(E, Decl(intersectionReduction.ts, 61, 37))
let r1 = f10(a1); // unknown
>r1 : Symbol(r1, Decl(intersectionReduction.ts, 69, 3))
>f10 : Symbol(f10, Decl(intersectionReduction.ts, 62, 37))
>a1 : Symbol(a1, Decl(intersectionReduction.ts, 66, 11))
let r2 = f10(a2); // string
>r2 : Symbol(r2, Decl(intersectionReduction.ts, 70, 3))
>f10 : Symbol(f10, Decl(intersectionReduction.ts, 62, 37))
>a2 : Symbol(a2, Decl(intersectionReduction.ts, 67, 11))
// Repro from #31663
const x1 = { a: 'foo', b: 42 };
>x1 : Symbol(x1, Decl(intersectionReduction.ts, 34, 5))
>a : Symbol(a, Decl(intersectionReduction.ts, 34, 12))
>b : Symbol(b, Decl(intersectionReduction.ts, 34, 22))
>x1 : Symbol(x1, Decl(intersectionReduction.ts, 74, 5))
>a : Symbol(a, Decl(intersectionReduction.ts, 74, 12))
>b : Symbol(b, Decl(intersectionReduction.ts, 74, 22))
const x2 = { a: 'foo', b: true };
>x2 : Symbol(x2, Decl(intersectionReduction.ts, 35, 5))
>a : Symbol(a, Decl(intersectionReduction.ts, 35, 12))
>b : Symbol(b, Decl(intersectionReduction.ts, 35, 22))
>x2 : Symbol(x2, Decl(intersectionReduction.ts, 75, 5))
>a : Symbol(a, Decl(intersectionReduction.ts, 75, 12))
>b : Symbol(b, Decl(intersectionReduction.ts, 75, 22))
declare let k: 'a' | 'b';
>k : Symbol(k, Decl(intersectionReduction.ts, 37, 11))
>k : Symbol(k, Decl(intersectionReduction.ts, 77, 11))
x1[k] = 'bar' as any; // Error
>x1 : Symbol(x1, Decl(intersectionReduction.ts, 34, 5))
>k : Symbol(k, Decl(intersectionReduction.ts, 37, 11))
>x1 : Symbol(x1, Decl(intersectionReduction.ts, 74, 5))
>k : Symbol(k, Decl(intersectionReduction.ts, 77, 11))
x2[k] = 'bar' as any; // Error
>x2 : Symbol(x2, Decl(intersectionReduction.ts, 35, 5))
>k : Symbol(k, Decl(intersectionReduction.ts, 37, 11))
>x2 : Symbol(x2, Decl(intersectionReduction.ts, 75, 5))
>k : Symbol(k, Decl(intersectionReduction.ts, 77, 11))
const enum Tag1 {}
>Tag1 : Symbol(Tag1, Decl(intersectionReduction.ts, 40, 21))
>Tag1 : Symbol(Tag1, Decl(intersectionReduction.ts, 80, 21))
const enum Tag2 {}
>Tag2 : Symbol(Tag2, Decl(intersectionReduction.ts, 42, 18))
>Tag2 : Symbol(Tag2, Decl(intersectionReduction.ts, 82, 18))
declare let s1: string & Tag1;
>s1 : Symbol(s1, Decl(intersectionReduction.ts, 45, 11))
>Tag1 : Symbol(Tag1, Decl(intersectionReduction.ts, 40, 21))
>s1 : Symbol(s1, Decl(intersectionReduction.ts, 85, 11))
>Tag1 : Symbol(Tag1, Decl(intersectionReduction.ts, 80, 21))
declare let s2: string & Tag2;
>s2 : Symbol(s2, Decl(intersectionReduction.ts, 46, 11))
>Tag2 : Symbol(Tag2, Decl(intersectionReduction.ts, 42, 18))
>s2 : Symbol(s2, Decl(intersectionReduction.ts, 86, 11))
>Tag2 : Symbol(Tag2, Decl(intersectionReduction.ts, 82, 18))
declare let t1: string & Tag1 | undefined;
>t1 : Symbol(t1, Decl(intersectionReduction.ts, 48, 11))
>Tag1 : Symbol(Tag1, Decl(intersectionReduction.ts, 40, 21))
>t1 : Symbol(t1, Decl(intersectionReduction.ts, 88, 11))
>Tag1 : Symbol(Tag1, Decl(intersectionReduction.ts, 80, 21))
declare let t2: string & Tag2 | undefined;
>t2 : Symbol(t2, Decl(intersectionReduction.ts, 49, 11))
>Tag2 : Symbol(Tag2, Decl(intersectionReduction.ts, 42, 18))
>t2 : Symbol(t2, Decl(intersectionReduction.ts, 89, 11))
>Tag2 : Symbol(Tag2, Decl(intersectionReduction.ts, 82, 18))
s1 = s2;
>s1 : Symbol(s1, Decl(intersectionReduction.ts, 45, 11))
>s2 : Symbol(s2, Decl(intersectionReduction.ts, 46, 11))
>s1 : Symbol(s1, Decl(intersectionReduction.ts, 85, 11))
>s2 : Symbol(s2, Decl(intersectionReduction.ts, 86, 11))
s2 = s1;
>s2 : Symbol(s2, Decl(intersectionReduction.ts, 46, 11))
>s1 : Symbol(s1, Decl(intersectionReduction.ts, 45, 11))
>s2 : Symbol(s2, Decl(intersectionReduction.ts, 86, 11))
>s1 : Symbol(s1, Decl(intersectionReduction.ts, 85, 11))
t1 = t2;
>t1 : Symbol(t1, Decl(intersectionReduction.ts, 48, 11))
>t2 : Symbol(t2, Decl(intersectionReduction.ts, 49, 11))
>t1 : Symbol(t1, Decl(intersectionReduction.ts, 88, 11))
>t2 : Symbol(t2, Decl(intersectionReduction.ts, 89, 11))
t2 = t1;
>t2 : Symbol(t2, Decl(intersectionReduction.ts, 49, 11))
>t1 : Symbol(t1, Decl(intersectionReduction.ts, 48, 11))
>t2 : Symbol(t2, Decl(intersectionReduction.ts, 89, 11))
>t1 : Symbol(t1, Decl(intersectionReduction.ts, 88, 11))
// Repro from #36736
const f1 = (t: "a" | ("b" & "c")): "a" => t;
>f1 : Symbol(f1, Decl(intersectionReduction.ts, 99, 5))
>t : Symbol(t, Decl(intersectionReduction.ts, 99, 12))
>t : Symbol(t, Decl(intersectionReduction.ts, 99, 12))
type Container<Type extends string> = {
>Container : Symbol(Container, Decl(intersectionReduction.ts, 99, 44))
>Type : Symbol(Type, Decl(intersectionReduction.ts, 101, 15))
type: Type;
>type : Symbol(type, Decl(intersectionReduction.ts, 101, 39))
>Type : Symbol(Type, Decl(intersectionReduction.ts, 101, 15))
}
const f2 = (t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a"> => t;
>f2 : Symbol(f2, Decl(intersectionReduction.ts, 105, 5))
>t : Symbol(t, Decl(intersectionReduction.ts, 105, 12))
>Container : Symbol(Container, Decl(intersectionReduction.ts, 99, 44))
>Container : Symbol(Container, Decl(intersectionReduction.ts, 99, 44))
>Container : Symbol(Container, Decl(intersectionReduction.ts, 99, 44))
>Container : Symbol(Container, Decl(intersectionReduction.ts, 99, 44))
>t : Symbol(t, Decl(intersectionReduction.ts, 105, 12))
const f3 = (t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t;
>f3 : Symbol(f3, Decl(intersectionReduction.ts, 106, 5))
>t : Symbol(t, Decl(intersectionReduction.ts, 106, 12))
>Container : Symbol(Container, Decl(intersectionReduction.ts, 99, 44))
>Container : Symbol(Container, Decl(intersectionReduction.ts, 99, 44))
>dataB : Symbol(dataB, Decl(intersectionReduction.ts, 106, 51))
>Container : Symbol(Container, Decl(intersectionReduction.ts, 99, 44))
>Container : Symbol(Container, Decl(intersectionReduction.ts, 99, 44))
>t : Symbol(t, Decl(intersectionReduction.ts, 106, 12))
const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t;
>f4 : Symbol(f4, Decl(intersectionReduction.ts, 107, 5))
>t : Symbol(t, Decl(intersectionReduction.ts, 107, 12))
>Container : Symbol(Container, Decl(intersectionReduction.ts, 99, 44))
>dataB : Symbol(dataB, Decl(intersectionReduction.ts, 107, 43))
>Container : Symbol(Container, Decl(intersectionReduction.ts, 99, 44))
>t : Symbol(t, Decl(intersectionReduction.ts, 107, 12))
@@ -88,6 +88,123 @@ type X6 = X | symbol & string;
type X7 = X | void & string;
>X7 : X
type A = { kind: 'a', foo: string };
>A : A
>kind : "a"
>foo : string
type B = { kind: 'b', foo: number };
>B : B
>kind : "b"
>foo : number
type C = { kind: 'c', foo: number };
>C : C
>kind : "c"
>foo : number
declare let ab: A & B;
>ab : never
ab.kind; // Error
>ab.kind : any
>ab : never
>kind : any
declare let x: A | (B & C); // A
>x : A
let a: A = x;
>a : A
>x : A
type AB = A & B; // never
>AB : never
type BC = B & C; // never
>BC : never
type U1 = Partial<A & B>; // never
>U1 : never
type U2 = Readonly<A & B>; // never
>U2 : never
type U3 = (A & B)['kind']; // never
>U3 : never
type U4 = A & B | B & C; // never
>U4 : never
type U5 = A | B & C; // A
>U5 : A
type K1 = keyof (A & B); // string | number | symbol
>K1 : string | number | symbol
type K2 = keyof A | keyof B; // 'kind' | 'foo'
>K2 : "kind" | "foo"
type Merge1<T, U> = { [P in keyof (T & U)]: P extends keyof T ? T[P] : U[P & keyof U] }
>Merge1 : Merge1<T, U>
type Merge2<T, U> = { [P in keyof T | keyof U]: P extends keyof T ? T[P] : U[P & keyof U] }
>Merge2 : Merge2<T, U>
type M1 = { a: 1, b: 2 } & { a: 2, c: 3 }; // never
>M1 : never
>a : 1
>b : 2
>a : 2
>c : 3
type M2 = Merge1<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // {}
>M2 : Merge1<{ a: 1; b: 2; }, { a: 2; c: 3; }>
>a : 1
>b : 2
>a : 2
>c : 3
type M3 = Merge2<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // { a: 1, b: 2, c: 3 }
>M3 : Merge2<{ a: 1; b: 2; }, { a: 2; c: 3; }>
>a : 1
>b : 2
>a : 2
>c : 3
type D = { kind: 'd', foo: unknown };
>D : D
>kind : "d"
>foo : unknown
type E = { kind: 'e', foo: unknown };
>E : E
>kind : "e"
>foo : unknown
declare function f10<T>(x: { foo: T }): T;
>f10 : <T>(x: { foo: T; }) => T
>x : { foo: T; }
>foo : T
declare let a1: A | D;
>a1 : A | D
declare let a2: A | D & E;
>a2 : A
let r1 = f10(a1); // unknown
>r1 : unknown
>f10(a1) : unknown
>f10 : <T>(x: { foo: T; }) => T
>a1 : A | D
let r2 = f10(a2); // string
>r2 : string
>f10(a2) : string
>f10 : <T>(x: { foo: T; }) => T
>a2 : A
// Repro from #31663
const x1 = { a: 'foo', b: 42 };
@@ -163,3 +280,38 @@ t2 = t1;
>t2 : undefined
>t1 : undefined
// Repro from #36736
const f1 = (t: "a" | ("b" & "c")): "a" => t;
>f1 : (t: "a") => "a"
>(t: "a" | ("b" & "c")): "a" => t : (t: "a") => "a"
>t : "a"
>t : "a"
type Container<Type extends string> = {
>Container : Container<Type>
type: Type;
>type : Type
}
const f2 = (t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a"> => t;
>f2 : (t: Container<"a">) => Container<"a">
>(t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a"> => t : (t: Container<"a">) => Container<"a">
>t : Container<"a">
>t : Container<"a">
const f3 = (t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t;
>f3 : (t: Container<"a">) => Container<"a">
>(t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t : (t: Container<"a">) => Container<"a">
>t : Container<"a">
>dataB : boolean
>t : Container<"a">
const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t;
>f4 : (t: number) => number
>(t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t : (t: number) => number
>t : number
>dataB : boolean
>t : number
@@ -1,8 +1,9 @@
tests/cases/conformance/types/intersection/intersectionReductionStrict.ts(40,1): error TS2322: Type 'any' is not assignable to type 'never'.
tests/cases/conformance/types/intersection/intersectionReductionStrict.ts(41,1): error TS2322: Type 'any' is not assignable to type 'never'.
tests/cases/conformance/types/intersection/intersectionReductionStrict.ts(38,4): error TS2339: Property 'kind' does not exist on type 'never'.
tests/cases/conformance/types/intersection/intersectionReductionStrict.ts(69,1): error TS2322: Type 'any' is not assignable to type 'never'.
tests/cases/conformance/types/intersection/intersectionReductionStrict.ts(70,1): error TS2322: Type 'any' is not assignable to type 'never'.
==== tests/cases/conformance/types/intersection/intersectionReductionStrict.ts (2 errors) ====
==== tests/cases/conformance/types/intersection/intersectionReductionStrict.ts (3 errors) ====
declare const sym1: unique symbol;
declare const sym2: unique symbol;
@@ -35,6 +36,37 @@ tests/cases/conformance/types/intersection/intersectionReductionStrict.ts(41,1):
type X6 = X | symbol & string;
type X7 = X | void & string;
type A = { kind: 'a', foo: string };
type B = { kind: 'b', foo: number };
type C = { kind: 'c', foo: number };
declare let ab: A & B;
ab.kind; // Error
~~~~
!!! error TS2339: Property 'kind' does not exist on type 'never'.
declare let x: A | (B & C); // A
let a: A = x;
type AB = A & B; // never
type BC = B & C; // never
type U1 = Partial<A & B>; // never
type U2 = Readonly<A & B>; // never
type U3 = (A & B)['kind']; // never
type U4 = A & B | B & C; // never
type U5 = A | B & C; // A
type K1 = keyof (A & B); // string | number | symbol
type K2 = keyof A | keyof B; // 'kind' | 'foo'
type Merge1<T, U> = { [P in keyof (T & U)]: P extends keyof T ? T[P] : U[P & keyof U] }
type Merge2<T, U> = { [P in keyof T | keyof U]: P extends keyof T ? T[P] : U[P & keyof U] }
type M1 = { a: 1, b: 2 } & { a: 2, c: 3 }; // never
type M2 = Merge1<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // {}
type M3 = Merge2<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // { a: 1, b: 2, c: 3 }
// Repro from #31663
const x1 = { a: 'foo', b: 42 };
@@ -63,4 +95,16 @@ tests/cases/conformance/types/intersection/intersectionReductionStrict.ts(41,1):
t1 = t2;
t2 = t1;
// Repro from #36736
const f1 = (t: "a" | ("b" & "c")): "a" => t;
type Container<Type extends string> = {
type: Type;
}
const f2 = (t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a"> => t;
const f3 = (t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t;
const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t;
@@ -31,6 +31,35 @@ type X5 = X | number & object;
type X6 = X | symbol & string;
type X7 = X | void & string;
type A = { kind: 'a', foo: string };
type B = { kind: 'b', foo: number };
type C = { kind: 'c', foo: number };
declare let ab: A & B;
ab.kind; // Error
declare let x: A | (B & C); // A
let a: A = x;
type AB = A & B; // never
type BC = B & C; // never
type U1 = Partial<A & B>; // never
type U2 = Readonly<A & B>; // never
type U3 = (A & B)['kind']; // never
type U4 = A & B | B & C; // never
type U5 = A | B & C; // A
type K1 = keyof (A & B); // string | number | symbol
type K2 = keyof A | keyof B; // 'kind' | 'foo'
type Merge1<T, U> = { [P in keyof (T & U)]: P extends keyof T ? T[P] : U[P & keyof U] }
type Merge2<T, U> = { [P in keyof T | keyof U]: P extends keyof T ? T[P] : U[P & keyof U] }
type M1 = { a: 1, b: 2 } & { a: 2, c: 3 }; // never
type M2 = Merge1<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // {}
type M3 = Merge2<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // { a: 1, b: 2, c: 3 }
// Repro from #31663
const x1 = { a: 'foo', b: 42 };
@@ -55,10 +84,24 @@ s2 = s1;
t1 = t2;
t2 = t1;
// Repro from #36736
const f1 = (t: "a" | ("b" & "c")): "a" => t;
type Container<Type extends string> = {
type: Type;
}
const f2 = (t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a"> => t;
const f3 = (t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t;
const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t;
//// [intersectionReductionStrict.js]
"use strict";
ab.kind; // Error
var a = x;
// Repro from #31663
var x1 = { a: 'foo', b: 42 };
var x2 = { a: 'foo', b: true };
@@ -68,3 +111,8 @@ s1 = s2;
s2 = s1;
t1 = t2;
t2 = t1;
// Repro from #36736
var f1 = function (t) { return t; };
var f2 = function (t) { return t; };
var f3 = function (t) { return t; };
var f4 = function (t) { return t; };
@@ -93,64 +93,244 @@ type X7 = X | void & string;
>X7 : Symbol(X7, Decl(intersectionReductionStrict.ts, 29, 30))
>X : Symbol(X, Decl(intersectionReductionStrict.ts, 20, 24))
type A = { kind: 'a', foo: string };
>A : Symbol(A, Decl(intersectionReductionStrict.ts, 30, 28))
>kind : Symbol(kind, Decl(intersectionReductionStrict.ts, 32, 10))
>foo : Symbol(foo, Decl(intersectionReductionStrict.ts, 32, 21))
type B = { kind: 'b', foo: number };
>B : Symbol(B, Decl(intersectionReductionStrict.ts, 32, 36))
>kind : Symbol(kind, Decl(intersectionReductionStrict.ts, 33, 10))
>foo : Symbol(foo, Decl(intersectionReductionStrict.ts, 33, 21))
type C = { kind: 'c', foo: number };
>C : Symbol(C, Decl(intersectionReductionStrict.ts, 33, 36))
>kind : Symbol(kind, Decl(intersectionReductionStrict.ts, 34, 10))
>foo : Symbol(foo, Decl(intersectionReductionStrict.ts, 34, 21))
declare let ab: A & B;
>ab : Symbol(ab, Decl(intersectionReductionStrict.ts, 36, 11))
>A : Symbol(A, Decl(intersectionReductionStrict.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReductionStrict.ts, 32, 36))
ab.kind; // Error
>ab : Symbol(ab, Decl(intersectionReductionStrict.ts, 36, 11))
declare let x: A | (B & C); // A
>x : Symbol(x, Decl(intersectionReductionStrict.ts, 39, 11))
>A : Symbol(A, Decl(intersectionReductionStrict.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReductionStrict.ts, 32, 36))
>C : Symbol(C, Decl(intersectionReductionStrict.ts, 33, 36))
let a: A = x;
>a : Symbol(a, Decl(intersectionReductionStrict.ts, 40, 3))
>A : Symbol(A, Decl(intersectionReductionStrict.ts, 30, 28))
>x : Symbol(x, Decl(intersectionReductionStrict.ts, 39, 11))
type AB = A & B; // never
>AB : Symbol(AB, Decl(intersectionReductionStrict.ts, 40, 13))
>A : Symbol(A, Decl(intersectionReductionStrict.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReductionStrict.ts, 32, 36))
type BC = B & C; // never
>BC : Symbol(BC, Decl(intersectionReductionStrict.ts, 42, 16))
>B : Symbol(B, Decl(intersectionReductionStrict.ts, 32, 36))
>C : Symbol(C, Decl(intersectionReductionStrict.ts, 33, 36))
type U1 = Partial<A & B>; // never
>U1 : Symbol(U1, Decl(intersectionReductionStrict.ts, 43, 16))
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
>A : Symbol(A, Decl(intersectionReductionStrict.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReductionStrict.ts, 32, 36))
type U2 = Readonly<A & B>; // never
>U2 : Symbol(U2, Decl(intersectionReductionStrict.ts, 45, 25))
>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --))
>A : Symbol(A, Decl(intersectionReductionStrict.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReductionStrict.ts, 32, 36))
type U3 = (A & B)['kind']; // never
>U3 : Symbol(U3, Decl(intersectionReductionStrict.ts, 46, 26))
>A : Symbol(A, Decl(intersectionReductionStrict.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReductionStrict.ts, 32, 36))
type U4 = A & B | B & C; // never
>U4 : Symbol(U4, Decl(intersectionReductionStrict.ts, 47, 26))
>A : Symbol(A, Decl(intersectionReductionStrict.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReductionStrict.ts, 32, 36))
>B : Symbol(B, Decl(intersectionReductionStrict.ts, 32, 36))
>C : Symbol(C, Decl(intersectionReductionStrict.ts, 33, 36))
type U5 = A | B & C; // A
>U5 : Symbol(U5, Decl(intersectionReductionStrict.ts, 48, 24))
>A : Symbol(A, Decl(intersectionReductionStrict.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReductionStrict.ts, 32, 36))
>C : Symbol(C, Decl(intersectionReductionStrict.ts, 33, 36))
type K1 = keyof (A & B); // string | number | symbol
>K1 : Symbol(K1, Decl(intersectionReductionStrict.ts, 49, 20))
>A : Symbol(A, Decl(intersectionReductionStrict.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReductionStrict.ts, 32, 36))
type K2 = keyof A | keyof B; // 'kind' | 'foo'
>K2 : Symbol(K2, Decl(intersectionReductionStrict.ts, 51, 24))
>A : Symbol(A, Decl(intersectionReductionStrict.ts, 30, 28))
>B : Symbol(B, Decl(intersectionReductionStrict.ts, 32, 36))
type Merge1<T, U> = { [P in keyof (T & U)]: P extends keyof T ? T[P] : U[P & keyof U] }
>Merge1 : Symbol(Merge1, Decl(intersectionReductionStrict.ts, 52, 28))
>T : Symbol(T, Decl(intersectionReductionStrict.ts, 54, 12))
>U : Symbol(U, Decl(intersectionReductionStrict.ts, 54, 14))
>P : Symbol(P, Decl(intersectionReductionStrict.ts, 54, 23))
>T : Symbol(T, Decl(intersectionReductionStrict.ts, 54, 12))
>U : Symbol(U, Decl(intersectionReductionStrict.ts, 54, 14))
>P : Symbol(P, Decl(intersectionReductionStrict.ts, 54, 23))
>T : Symbol(T, Decl(intersectionReductionStrict.ts, 54, 12))
>T : Symbol(T, Decl(intersectionReductionStrict.ts, 54, 12))
>P : Symbol(P, Decl(intersectionReductionStrict.ts, 54, 23))
>U : Symbol(U, Decl(intersectionReductionStrict.ts, 54, 14))
>P : Symbol(P, Decl(intersectionReductionStrict.ts, 54, 23))
>U : Symbol(U, Decl(intersectionReductionStrict.ts, 54, 14))
type Merge2<T, U> = { [P in keyof T | keyof U]: P extends keyof T ? T[P] : U[P & keyof U] }
>Merge2 : Symbol(Merge2, Decl(intersectionReductionStrict.ts, 54, 87))
>T : Symbol(T, Decl(intersectionReductionStrict.ts, 55, 12))
>U : Symbol(U, Decl(intersectionReductionStrict.ts, 55, 14))
>P : Symbol(P, Decl(intersectionReductionStrict.ts, 55, 23))
>T : Symbol(T, Decl(intersectionReductionStrict.ts, 55, 12))
>U : Symbol(U, Decl(intersectionReductionStrict.ts, 55, 14))
>P : Symbol(P, Decl(intersectionReductionStrict.ts, 55, 23))
>T : Symbol(T, Decl(intersectionReductionStrict.ts, 55, 12))
>T : Symbol(T, Decl(intersectionReductionStrict.ts, 55, 12))
>P : Symbol(P, Decl(intersectionReductionStrict.ts, 55, 23))
>U : Symbol(U, Decl(intersectionReductionStrict.ts, 55, 14))
>P : Symbol(P, Decl(intersectionReductionStrict.ts, 55, 23))
>U : Symbol(U, Decl(intersectionReductionStrict.ts, 55, 14))
type M1 = { a: 1, b: 2 } & { a: 2, c: 3 }; // never
>M1 : Symbol(M1, Decl(intersectionReductionStrict.ts, 55, 91))
>a : Symbol(a, Decl(intersectionReductionStrict.ts, 57, 11))
>b : Symbol(b, Decl(intersectionReductionStrict.ts, 57, 17))
>a : Symbol(a, Decl(intersectionReductionStrict.ts, 57, 28))
>c : Symbol(c, Decl(intersectionReductionStrict.ts, 57, 34))
type M2 = Merge1<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // {}
>M2 : Symbol(M2, Decl(intersectionReductionStrict.ts, 57, 42))
>Merge1 : Symbol(Merge1, Decl(intersectionReductionStrict.ts, 52, 28))
>a : Symbol(a, Decl(intersectionReductionStrict.ts, 58, 18))
>b : Symbol(b, Decl(intersectionReductionStrict.ts, 58, 24))
>a : Symbol(a, Decl(intersectionReductionStrict.ts, 58, 34))
>c : Symbol(c, Decl(intersectionReductionStrict.ts, 58, 40))
type M3 = Merge2<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // { a: 1, b: 2, c: 3 }
>M3 : Symbol(M3, Decl(intersectionReductionStrict.ts, 58, 49))
>Merge2 : Symbol(Merge2, Decl(intersectionReductionStrict.ts, 54, 87))
>a : Symbol(a, Decl(intersectionReductionStrict.ts, 59, 18))
>b : Symbol(b, Decl(intersectionReductionStrict.ts, 59, 24))
>a : Symbol(a, Decl(intersectionReductionStrict.ts, 59, 34))
>c : Symbol(c, Decl(intersectionReductionStrict.ts, 59, 40))
// Repro from #31663
const x1 = { a: 'foo', b: 42 };
>x1 : Symbol(x1, Decl(intersectionReductionStrict.ts, 34, 5))
>a : Symbol(a, Decl(intersectionReductionStrict.ts, 34, 12))
>b : Symbol(b, Decl(intersectionReductionStrict.ts, 34, 22))
>x1 : Symbol(x1, Decl(intersectionReductionStrict.ts, 63, 5))
>a : Symbol(a, Decl(intersectionReductionStrict.ts, 63, 12))
>b : Symbol(b, Decl(intersectionReductionStrict.ts, 63, 22))
const x2 = { a: 'foo', b: true };
>x2 : Symbol(x2, Decl(intersectionReductionStrict.ts, 35, 5))
>a : Symbol(a, Decl(intersectionReductionStrict.ts, 35, 12))
>b : Symbol(b, Decl(intersectionReductionStrict.ts, 35, 22))
>x2 : Symbol(x2, Decl(intersectionReductionStrict.ts, 64, 5))
>a : Symbol(a, Decl(intersectionReductionStrict.ts, 64, 12))
>b : Symbol(b, Decl(intersectionReductionStrict.ts, 64, 22))
declare let k: 'a' | 'b';
>k : Symbol(k, Decl(intersectionReductionStrict.ts, 37, 11))
>k : Symbol(k, Decl(intersectionReductionStrict.ts, 66, 11))
x1[k] = 'bar' as any; // Error
>x1 : Symbol(x1, Decl(intersectionReductionStrict.ts, 34, 5))
>k : Symbol(k, Decl(intersectionReductionStrict.ts, 37, 11))
>x1 : Symbol(x1, Decl(intersectionReductionStrict.ts, 63, 5))
>k : Symbol(k, Decl(intersectionReductionStrict.ts, 66, 11))
x2[k] = 'bar' as any; // Error
>x2 : Symbol(x2, Decl(intersectionReductionStrict.ts, 35, 5))
>k : Symbol(k, Decl(intersectionReductionStrict.ts, 37, 11))
>x2 : Symbol(x2, Decl(intersectionReductionStrict.ts, 64, 5))
>k : Symbol(k, Decl(intersectionReductionStrict.ts, 66, 11))
const enum Tag1 {}
>Tag1 : Symbol(Tag1, Decl(intersectionReductionStrict.ts, 40, 21))
>Tag1 : Symbol(Tag1, Decl(intersectionReductionStrict.ts, 69, 21))
const enum Tag2 {}
>Tag2 : Symbol(Tag2, Decl(intersectionReductionStrict.ts, 42, 18))
>Tag2 : Symbol(Tag2, Decl(intersectionReductionStrict.ts, 71, 18))
declare let s1: string & Tag1;
>s1 : Symbol(s1, Decl(intersectionReductionStrict.ts, 45, 11))
>Tag1 : Symbol(Tag1, Decl(intersectionReductionStrict.ts, 40, 21))
>s1 : Symbol(s1, Decl(intersectionReductionStrict.ts, 74, 11))
>Tag1 : Symbol(Tag1, Decl(intersectionReductionStrict.ts, 69, 21))
declare let s2: string & Tag2;
>s2 : Symbol(s2, Decl(intersectionReductionStrict.ts, 46, 11))
>Tag2 : Symbol(Tag2, Decl(intersectionReductionStrict.ts, 42, 18))
>s2 : Symbol(s2, Decl(intersectionReductionStrict.ts, 75, 11))
>Tag2 : Symbol(Tag2, Decl(intersectionReductionStrict.ts, 71, 18))
declare let t1: string & Tag1 | undefined;
>t1 : Symbol(t1, Decl(intersectionReductionStrict.ts, 48, 11))
>Tag1 : Symbol(Tag1, Decl(intersectionReductionStrict.ts, 40, 21))
>t1 : Symbol(t1, Decl(intersectionReductionStrict.ts, 77, 11))
>Tag1 : Symbol(Tag1, Decl(intersectionReductionStrict.ts, 69, 21))
declare let t2: string & Tag2 | undefined;
>t2 : Symbol(t2, Decl(intersectionReductionStrict.ts, 49, 11))
>Tag2 : Symbol(Tag2, Decl(intersectionReductionStrict.ts, 42, 18))
>t2 : Symbol(t2, Decl(intersectionReductionStrict.ts, 78, 11))
>Tag2 : Symbol(Tag2, Decl(intersectionReductionStrict.ts, 71, 18))
s1 = s2;
>s1 : Symbol(s1, Decl(intersectionReductionStrict.ts, 45, 11))
>s2 : Symbol(s2, Decl(intersectionReductionStrict.ts, 46, 11))
>s1 : Symbol(s1, Decl(intersectionReductionStrict.ts, 74, 11))
>s2 : Symbol(s2, Decl(intersectionReductionStrict.ts, 75, 11))
s2 = s1;
>s2 : Symbol(s2, Decl(intersectionReductionStrict.ts, 46, 11))
>s1 : Symbol(s1, Decl(intersectionReductionStrict.ts, 45, 11))
>s2 : Symbol(s2, Decl(intersectionReductionStrict.ts, 75, 11))
>s1 : Symbol(s1, Decl(intersectionReductionStrict.ts, 74, 11))
t1 = t2;
>t1 : Symbol(t1, Decl(intersectionReductionStrict.ts, 48, 11))
>t2 : Symbol(t2, Decl(intersectionReductionStrict.ts, 49, 11))
>t1 : Symbol(t1, Decl(intersectionReductionStrict.ts, 77, 11))
>t2 : Symbol(t2, Decl(intersectionReductionStrict.ts, 78, 11))
t2 = t1;
>t2 : Symbol(t2, Decl(intersectionReductionStrict.ts, 49, 11))
>t1 : Symbol(t1, Decl(intersectionReductionStrict.ts, 48, 11))
>t2 : Symbol(t2, Decl(intersectionReductionStrict.ts, 78, 11))
>t1 : Symbol(t1, Decl(intersectionReductionStrict.ts, 77, 11))
// Repro from #36736
const f1 = (t: "a" | ("b" & "c")): "a" => t;
>f1 : Symbol(f1, Decl(intersectionReductionStrict.ts, 88, 5))
>t : Symbol(t, Decl(intersectionReductionStrict.ts, 88, 12))
>t : Symbol(t, Decl(intersectionReductionStrict.ts, 88, 12))
type Container<Type extends string> = {
>Container : Symbol(Container, Decl(intersectionReductionStrict.ts, 88, 44))
>Type : Symbol(Type, Decl(intersectionReductionStrict.ts, 90, 15))
type: Type;
>type : Symbol(type, Decl(intersectionReductionStrict.ts, 90, 39))
>Type : Symbol(Type, Decl(intersectionReductionStrict.ts, 90, 15))
}
const f2 = (t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a"> => t;
>f2 : Symbol(f2, Decl(intersectionReductionStrict.ts, 94, 5))
>t : Symbol(t, Decl(intersectionReductionStrict.ts, 94, 12))
>Container : Symbol(Container, Decl(intersectionReductionStrict.ts, 88, 44))
>Container : Symbol(Container, Decl(intersectionReductionStrict.ts, 88, 44))
>Container : Symbol(Container, Decl(intersectionReductionStrict.ts, 88, 44))
>Container : Symbol(Container, Decl(intersectionReductionStrict.ts, 88, 44))
>t : Symbol(t, Decl(intersectionReductionStrict.ts, 94, 12))
const f3 = (t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t;
>f3 : Symbol(f3, Decl(intersectionReductionStrict.ts, 95, 5))
>t : Symbol(t, Decl(intersectionReductionStrict.ts, 95, 12))
>Container : Symbol(Container, Decl(intersectionReductionStrict.ts, 88, 44))
>Container : Symbol(Container, Decl(intersectionReductionStrict.ts, 88, 44))
>dataB : Symbol(dataB, Decl(intersectionReductionStrict.ts, 95, 51))
>Container : Symbol(Container, Decl(intersectionReductionStrict.ts, 88, 44))
>Container : Symbol(Container, Decl(intersectionReductionStrict.ts, 88, 44))
>t : Symbol(t, Decl(intersectionReductionStrict.ts, 95, 12))
const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t;
>f4 : Symbol(f4, Decl(intersectionReductionStrict.ts, 96, 5))
>t : Symbol(t, Decl(intersectionReductionStrict.ts, 96, 12))
>Container : Symbol(Container, Decl(intersectionReductionStrict.ts, 88, 44))
>dataB : Symbol(dataB, Decl(intersectionReductionStrict.ts, 96, 43))
>Container : Symbol(Container, Decl(intersectionReductionStrict.ts, 88, 44))
>t : Symbol(t, Decl(intersectionReductionStrict.ts, 96, 12))
@@ -88,6 +88,90 @@ type X6 = X | symbol & string;
type X7 = X | void & string;
>X7 : X
type A = { kind: 'a', foo: string };
>A : A
>kind : "a"
>foo : string
type B = { kind: 'b', foo: number };
>B : B
>kind : "b"
>foo : number
type C = { kind: 'c', foo: number };
>C : C
>kind : "c"
>foo : number
declare let ab: A & B;
>ab : never
ab.kind; // Error
>ab.kind : any
>ab : never
>kind : any
declare let x: A | (B & C); // A
>x : A
let a: A = x;
>a : A
>x : A
type AB = A & B; // never
>AB : never
type BC = B & C; // never
>BC : never
type U1 = Partial<A & B>; // never
>U1 : never
type U2 = Readonly<A & B>; // never
>U2 : never
type U3 = (A & B)['kind']; // never
>U3 : never
type U4 = A & B | B & C; // never
>U4 : never
type U5 = A | B & C; // A
>U5 : A
type K1 = keyof (A & B); // string | number | symbol
>K1 : string | number | symbol
type K2 = keyof A | keyof B; // 'kind' | 'foo'
>K2 : "kind" | "foo"
type Merge1<T, U> = { [P in keyof (T & U)]: P extends keyof T ? T[P] : U[P & keyof U] }
>Merge1 : Merge1<T, U>
type Merge2<T, U> = { [P in keyof T | keyof U]: P extends keyof T ? T[P] : U[P & keyof U] }
>Merge2 : Merge2<T, U>
type M1 = { a: 1, b: 2 } & { a: 2, c: 3 }; // never
>M1 : never
>a : 1
>b : 2
>a : 2
>c : 3
type M2 = Merge1<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // {}
>M2 : Merge1<{ a: 1; b: 2; }, { a: 2; c: 3; }>
>a : 1
>b : 2
>a : 2
>c : 3
type M3 = Merge2<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // { a: 1, b: 2, c: 3 }
>M3 : Merge2<{ a: 1; b: 2; }, { a: 2; c: 3; }>
>a : 1
>b : 2
>a : 2
>c : 3
// Repro from #31663
const x1 = { a: 'foo', b: 42 };
@@ -163,3 +247,38 @@ t2 = t1;
>t2 : undefined
>t1 : undefined
// Repro from #36736
const f1 = (t: "a" | ("b" & "c")): "a" => t;
>f1 : (t: "a") => "a"
>(t: "a" | ("b" & "c")): "a" => t : (t: "a") => "a"
>t : "a"
>t : "a"
type Container<Type extends string> = {
>Container : Container<Type>
type: Type;
>type : Type
}
const f2 = (t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a"> => t;
>f2 : (t: Container<"a">) => Container<"a">
>(t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a"> => t : (t: Container<"a">) => Container<"a">
>t : Container<"a">
>t : Container<"a">
const f3 = (t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t;
>f3 : (t: Container<"a">) => Container<"a">
>(t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t : (t: Container<"a">) => Container<"a">
>t : Container<"a">
>dataB : boolean
>t : Container<"a">
const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t;
>f4 : (t: number) => number
>(t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t : (t: number) => number
>t : number
>dataB : boolean
>t : number
+1 -1
View File
@@ -565,7 +565,7 @@ let overwriteId: { id: string, a: number, c: number, d: string } =
>d : string
f({ a: 1, id: true }, { c: 1, d: 'no' })
>f({ a: 1, id: true }, { c: 1, d: 'no' }) : { a: number; id: boolean; } & { c: number; d: string; } & { id: string; }
>f({ a: 1, id: true }, { c: 1, d: 'no' }) : never
>f : <T, U>(t: T, u: U) => T & U & { id: string; }
>{ a: 1, id: true } : { a: number; id: true; }
>a : number
@@ -6,9 +6,10 @@ tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(11,6): error TS2456
tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(12,11): error TS2313: Type parameter 'K' has a circular constraint.
tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(20,19): error TS2589: Type instantiation is excessively deep and possibly infinite.
tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(66,25): error TS2313: Type parameter 'P' has a circular constraint.
tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(79,1): error TS2615: Type of property '"each"' circularly references itself in mapped type '{ type: never; minimum_count: never; maximum_count: never; collapsable?: never; each: never; }'.
==== tests/cases/conformance/types/mapped/recursiveMappedTypes.ts (8 errors) ====
==== tests/cases/conformance/types/mapped/recursiveMappedTypes.ts (9 errors) ====
// Recursive mapped types simply appear empty
type Recurse = {
@@ -106,4 +107,6 @@ tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(66,25): error TS231
declare let x: ListChild;
x.type;
~~~~~~
!!! error TS2615: Type of property '"each"' circularly references itself in mapped type '{ type: never; minimum_count: never; maximum_count: never; collapsable?: never; each: never; }'.
@@ -93,6 +93,6 @@ if (!hasKind(x, "B")) {
}
else {
let d = x;
>d : A & B
>x : A & B
>d : never
>x : never
}
@@ -88,6 +88,6 @@ if (!hasKind(x, "B")) {
}
else {
let d = x;
>d : A & B
>x : A & B
>d : never
>x : never
}
@@ -92,6 +92,6 @@ if (!hasKind(x, "B")) {
}
else {
let d = x;
>d : A & B
>x : A & B
>d : never
>x : never
}
@@ -15,5 +15,4 @@ tests/cases/conformance/jsx/file.tsx(12,10): error TS2322: Type 'true' is not as
var SFCComp = SFC1 || SFC2;
<SFCComp x />
~
!!! error TS2322: Type 'true' is not assignable to type 'never'.
!!! related TS6500 tests/cases/conformance/jsx/file.tsx:3:23: The expected type comes from property 'x' which is declared here on type 'IntrinsicAttributes & { x: number; } & { x: boolean; }'
!!! error TS2322: Type 'true' is not assignable to type 'never'.
@@ -15,5 +15,4 @@ tests/cases/conformance/jsx/file.tsx(12,10): error TS2322: Type 'string' is not
var SFCComp = SFC1 || SFC2;
<SFCComp x={"hi"}/>
~
!!! error TS2322: Type 'string' is not assignable to type 'never'.
!!! related TS6500 tests/cases/conformance/jsx/file.tsx:3:23: The expected type comes from property 'x' which is declared here on type 'IntrinsicAttributes & { x: number; } & { x: boolean; }'
!!! error TS2322: Type 'string' is not assignable to type 'never'.
@@ -0,0 +1,14 @@
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20): error TS2339: Property 'global' does not exist on type 'never'.
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts (1 errors) ====
interface I { global: string; }
var result: I;
var result2: I;
if (!(result instanceof RegExp)) {
result = result2;
} else if (!result.global) {
~~~~~~
!!! error TS2339: Property 'global' does not exist on type 'never'.
}
@@ -20,7 +20,5 @@ if (!(result instanceof RegExp)) {
>result2 : Symbol(result2, Decl(typeGuardsWithInstanceOf.ts, 2, 3))
} else if (!result.global) {
>result.global : Symbol(global, Decl(typeGuardsWithInstanceOf.ts, 0, 13), Decl(lib.es5.d.ts, --, --))
>result : Symbol(result, Decl(typeGuardsWithInstanceOf.ts, 1, 3))
>global : Symbol(global, Decl(typeGuardsWithInstanceOf.ts, 0, 13), Decl(lib.es5.d.ts, --, --))
}
@@ -22,7 +22,7 @@ if (!(result instanceof RegExp)) {
} else if (!result.global) {
>!result.global : boolean
>result.global : never
>result : I & RegExp
>global : never
>result.global : any
>result : never
>global : any
}
@@ -32,6 +32,46 @@ type X5 = X | number & object;
type X6 = X | symbol & string;
type X7 = X | void & string;
type A = { kind: 'a', foo: string };
type B = { kind: 'b', foo: number };
type C = { kind: 'c', foo: number };
declare let ab: A & B;
ab.kind; // Error
declare let x: A | (B & C); // A
let a: A = x;
type AB = A & B; // never
type BC = B & C; // never
type U1 = Partial<A & B>; // never
type U2 = Readonly<A & B>; // never
type U3 = (A & B)['kind']; // never
type U4 = A & B | B & C; // never
type U5 = A | B & C; // A
type K1 = keyof (A & B); // string | number | symbol
type K2 = keyof A | keyof B; // 'kind' | 'foo'
type Merge1<T, U> = { [P in keyof (T & U)]: P extends keyof T ? T[P] : U[P & keyof U] }
type Merge2<T, U> = { [P in keyof T | keyof U]: P extends keyof T ? T[P] : U[P & keyof U] }
type M1 = { a: 1, b: 2 } & { a: 2, c: 3 }; // never
type M2 = Merge1<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // {}
type M3 = Merge2<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // { a: 1, b: 2, c: 3 }
type D = { kind: 'd', foo: unknown };
type E = { kind: 'e', foo: unknown };
declare function f10<T>(x: { foo: T }): T;
declare let a1: A | D;
declare let a2: A | D & E;
let r1 = f10(a1); // unknown
let r2 = f10(a2); // string
// Repro from #31663
const x1 = { a: 'foo', b: 42 };
@@ -56,3 +96,15 @@ s2 = s1;
t1 = t2;
t2 = t1;
// Repro from #36736
const f1 = (t: "a" | ("b" & "c")): "a" => t;
type Container<Type extends string> = {
type: Type;
}
const f2 = (t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a"> => t;
const f3 = (t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t;
const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t;
@@ -32,6 +32,35 @@ type X5 = X | number & object;
type X6 = X | symbol & string;
type X7 = X | void & string;
type A = { kind: 'a', foo: string };
type B = { kind: 'b', foo: number };
type C = { kind: 'c', foo: number };
declare let ab: A & B;
ab.kind; // Error
declare let x: A | (B & C); // A
let a: A = x;
type AB = A & B; // never
type BC = B & C; // never
type U1 = Partial<A & B>; // never
type U2 = Readonly<A & B>; // never
type U3 = (A & B)['kind']; // never
type U4 = A & B | B & C; // never
type U5 = A | B & C; // A
type K1 = keyof (A & B); // string | number | symbol
type K2 = keyof A | keyof B; // 'kind' | 'foo'
type Merge1<T, U> = { [P in keyof (T & U)]: P extends keyof T ? T[P] : U[P & keyof U] }
type Merge2<T, U> = { [P in keyof T | keyof U]: P extends keyof T ? T[P] : U[P & keyof U] }
type M1 = { a: 1, b: 2 } & { a: 2, c: 3 }; // never
type M2 = Merge1<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // {}
type M3 = Merge2<{ a: 1, b: 2 }, { a: 2, c: 3 }>; // { a: 1, b: 2, c: 3 }
// Repro from #31663
const x1 = { a: 'foo', b: 42 };
@@ -56,3 +85,15 @@ s2 = s1;
t1 = t2;
t2 = t1;
// Repro from #36736
const f1 = (t: "a" | ("b" & "c")): "a" => t;
type Container<Type extends string> = {
type: Type;
}
const f2 = (t: Container<"a"> | (Container<"b"> & Container<"c">)): Container<"a"> => t;
const f3 = (t: Container<"a"> | (Container<"b"> & { dataB: boolean } & Container<"a">)): Container<"a"> => t;
const f4 = (t: number | (Container<"b"> & { dataB: boolean } & Container<"a">)): number => t;
@@ -131,7 +131,7 @@ function foo1(x: RuntimeValue & { type: 'number' }) {
x.value; // number
}
else {
x.value; // Error, x is never
x.value; // number
}
}
@@ -1,14 +0,0 @@
/// <reference path='fourslash.ts'/>
// #32708
////interface I<T> {
//// /** only once please */
//// t: T
////}
////interface C<T> extends I<T> {
//// t: T
////}
////declare var cnsb: C<number> & C<string> & C<boolean>;
////cnsb.t/**/
verify.quickInfoAt("", "(property) C<T>.t: never", "only once please");
@@ -1,22 +0,0 @@
/// <reference path='fourslash.ts' />
//@Filename: file.tsx
// @jsx: preserve
// @skipLibCheck: true
//// declare module JSX {
//// interface Element { }
//// interface IntrinsicElements {
//// }
//// interface ElementAttributesProperty { props; }
//// }
//// function SFC1(prop: { x: number }) {
//// return <div>hello </div>;
//// };
//// function SFC2(prop: { x: boolean }) {
//// return <h1>World </h1>;
//// }
//// var SFCComp = SFC1 || SFC2;
//// <SFCComp /**/ />
verify.completions({ marker: "", exact: ["x"] });