Merge pull request #30779 from Microsoft/relateDiscriminants
Relate source types covered by a target discriminated union
This commit is contained in:
commit
2d8527f3f0
|
@ -12485,7 +12485,7 @@ namespace ts {
|
|||
if (result && isPerformingExcessPropertyChecks) {
|
||||
// Validate against excess props using the original `source`
|
||||
const discriminantType = target.flags & TypeFlags.Union ? findMatchingDiscriminantType(source, target as UnionType) : undefined;
|
||||
if (!propertiesRelatedTo(source, discriminantType || target, reportErrors)) {
|
||||
if (!propertiesRelatedTo(source, discriminantType || target, reportErrors, /*excludedProperties*/ undefined)) {
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
|
@ -12495,7 +12495,7 @@ namespace ts {
|
|||
result = typeRelatedToEachType(getRegularTypeOfObjectLiteral(source), target as IntersectionType, reportErrors);
|
||||
if (result && isPerformingExcessPropertyChecks) {
|
||||
// Validate against excess props using the original `source`
|
||||
if (!propertiesRelatedTo(source, target, reportErrors)) {
|
||||
if (!propertiesRelatedTo(source, target, reportErrors, /*excludedProperties*/ undefined)) {
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
|
@ -13173,7 +13173,7 @@ namespace ts {
|
|||
if (source.flags & (TypeFlags.Object | TypeFlags.Intersection) && target.flags & TypeFlags.Object) {
|
||||
// Report structural errors only if we haven't reported any errors yet
|
||||
const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo && !sourceIsPrimitive;
|
||||
result = propertiesRelatedTo(source, target, reportStructuralErrors);
|
||||
result = propertiesRelatedTo(source, target, reportStructuralErrors, /*excludedProperties*/ undefined);
|
||||
if (result) {
|
||||
result &= signaturesRelatedTo(source, target, SignatureKind.Call, reportStructuralErrors);
|
||||
if (result) {
|
||||
|
@ -13193,6 +13193,19 @@ namespace ts {
|
|||
return result;
|
||||
}
|
||||
}
|
||||
// If S is an object type and T is a discriminated union, S may be related to T if
|
||||
// there exists a constituent of T for every combination of the discriminants of S
|
||||
// with respect to T. We do not report errors here, as we will use the existing
|
||||
// error result from checking each constituent of the union.
|
||||
if (source.flags & (TypeFlags.Object | TypeFlags.Intersection) && target.flags & TypeFlags.Union) {
|
||||
const objectOnlyTarget = extractTypesOfKind(target, TypeFlags.Object);
|
||||
if (objectOnlyTarget.flags & TypeFlags.Union) {
|
||||
const result = typeRelatedToDiscriminatedType(source, objectOnlyTarget as UnionType);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ternary.False;
|
||||
|
||||
|
@ -13256,9 +13269,185 @@ namespace ts {
|
|||
return Ternary.False;
|
||||
}
|
||||
|
||||
function propertiesRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
|
||||
function typeRelatedToDiscriminatedType(source: Type, target: UnionType) {
|
||||
// 1. Generate the combinations of discriminant properties & types 'source' can satisfy.
|
||||
// a. If the number of combinations is above a set limit, the comparison is too complex.
|
||||
// 2. Filter 'target' to the subset of types whose discriminants exist in the matrix.
|
||||
// a. If 'target' does not satisfy all discriminants in the matrix, 'source' is not related.
|
||||
// 3. For each type in the filtered 'target', determine if all non-discriminant properties of
|
||||
// 'target' are related to a property in 'source'.
|
||||
//
|
||||
// NOTE: See ~/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts
|
||||
// for examples.
|
||||
|
||||
const sourceProperties = getPropertiesOfObjectType(source);
|
||||
const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target);
|
||||
if (!sourcePropertiesFiltered) return Ternary.False;
|
||||
|
||||
// Though we could compute the number of combinations as we generate
|
||||
// the matrix, this would incur additional memory overhead due to
|
||||
// array allocations. To reduce this overhead, we first compute
|
||||
// the number of combinations to ensure we will not surpass our
|
||||
// fixed limit before incurring the cost of any allocations:
|
||||
let numCombinations = 1;
|
||||
for (const sourceProperty of sourcePropertiesFiltered) {
|
||||
numCombinations *= countTypes(getTypeOfSymbol(sourceProperty));
|
||||
if (numCombinations > 25) {
|
||||
// We've reached the complexity limit.
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the set of types for each discriminant property.
|
||||
const sourceDiscriminantTypes: Type[][] = new Array<Type[]>(sourcePropertiesFiltered.length);
|
||||
const excludedProperties = createUnderscoreEscapedMap<true>();
|
||||
for (let i = 0; i < sourcePropertiesFiltered.length; i++) {
|
||||
const sourceProperty = sourcePropertiesFiltered[i];
|
||||
const sourcePropertyType = getTypeOfSymbol(sourceProperty);
|
||||
sourceDiscriminantTypes[i] = sourcePropertyType.flags & TypeFlags.Union
|
||||
? (sourcePropertyType as UnionType).types
|
||||
: [sourcePropertyType];
|
||||
excludedProperties.set(sourceProperty.escapedName, true);
|
||||
}
|
||||
|
||||
// Match each combination of the cartesian product of discriminant properties to one or more
|
||||
// constituents of 'target'. If any combination does not have a match then 'source' is not relatable.
|
||||
const discriminantCombinations = cartesianProduct(sourceDiscriminantTypes);
|
||||
const matchingTypes: Type[] = [];
|
||||
for (const combination of discriminantCombinations) {
|
||||
let hasMatch = false;
|
||||
outer: for (const type of target.types) {
|
||||
for (let i = 0; i < sourcePropertiesFiltered.length; i++) {
|
||||
const sourceProperty = sourcePropertiesFiltered[i];
|
||||
const targetProperty = getPropertyOfObjectType(type, sourceProperty.escapedName);
|
||||
if (!targetProperty) continue outer;
|
||||
if (sourceProperty === targetProperty) continue;
|
||||
// We compare the source property to the target in the context of a single discriminant type.
|
||||
const related = propertyRelatedTo(source, target, sourceProperty, targetProperty, _ => combination[i], /*reportErrors*/ false);
|
||||
// If the target property could not be found, or if the properties were not related,
|
||||
// then this constituent is not a match.
|
||||
if (!related) {
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
pushIfUnique(matchingTypes, type, equateValues);
|
||||
hasMatch = true;
|
||||
}
|
||||
if (!hasMatch) {
|
||||
// We failed to match any type for this combination.
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the remaining non-discriminant properties of each match.
|
||||
let result = Ternary.True;
|
||||
for (const type of matchingTypes) {
|
||||
result &= propertiesRelatedTo(source, type, /*reportErrors*/ false, excludedProperties);
|
||||
if (result) {
|
||||
result &= signaturesRelatedTo(source, type, SignatureKind.Call, /*reportStructuralErrors*/ false);
|
||||
if (result) {
|
||||
result &= signaturesRelatedTo(source, type, SignatureKind.Construct, /*reportStructuralErrors*/ false);
|
||||
if (result) {
|
||||
result &= indexTypesRelatedTo(source, type, IndexKind.String, /*sourceIsPrimitive*/ false, /*reportStructuralErrors*/ false);
|
||||
if (result) {
|
||||
result &= indexTypesRelatedTo(source, type, IndexKind.Number, /*sourceIsPrimitive*/ false, /*reportStructuralErrors*/ false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function excludeProperties(properties: Symbol[], excludedProperties: UnderscoreEscapedMap<true> | undefined) {
|
||||
if (!excludedProperties || properties.length === 0) return properties;
|
||||
let result: Symbol[] | undefined;
|
||||
for (let i = 0; i < properties.length; i++) {
|
||||
if (!excludedProperties.has(properties[i].escapedName)) {
|
||||
if (result) {
|
||||
result.push(properties[i]);
|
||||
}
|
||||
}
|
||||
else if (!result) {
|
||||
result = properties.slice(0, i);
|
||||
}
|
||||
}
|
||||
return result || properties;
|
||||
}
|
||||
|
||||
function propertyRelatedTo(source: Type, target: Type, sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean): Ternary {
|
||||
const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp);
|
||||
const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp);
|
||||
if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) {
|
||||
const hasDifferingDeclarations = sourceProp.valueDeclaration !== targetProp.valueDeclaration;
|
||||
if (getCheckFlags(sourceProp) & CheckFlags.ContainsPrivate && hasDifferingDeclarations) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Property_0_has_conflicting_declarations_and_is_inaccessible_in_type_1, symbolToString(sourceProp), typeToString(source));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
if (hasDifferingDeclarations) {
|
||||
if (reportErrors) {
|
||||
if (sourcePropFlags & ModifierFlags.Private && targetPropFlags & ModifierFlags.Private) {
|
||||
reportError(Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp));
|
||||
}
|
||||
else {
|
||||
reportError(Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp),
|
||||
typeToString(sourcePropFlags & ModifierFlags.Private ? source : target),
|
||||
typeToString(sourcePropFlags & ModifierFlags.Private ? target : source));
|
||||
}
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
else if (targetPropFlags & ModifierFlags.Protected) {
|
||||
if (!isValidOverrideOf(sourceProp, targetProp)) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, symbolToString(targetProp),
|
||||
typeToString(getDeclaringClass(sourceProp) || source), typeToString(getDeclaringClass(targetProp) || target));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
else if (sourcePropFlags & ModifierFlags.Protected) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2,
|
||||
symbolToString(targetProp), typeToString(source), typeToString(target));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
// If the target comes from a partial union prop, allow `undefined` in the target type
|
||||
const related = isRelatedTo(getTypeOfSourceProperty(sourceProp), addOptionality(getTypeOfSymbol(targetProp), !!(getCheckFlags(targetProp) & CheckFlags.Partial)), reportErrors);
|
||||
if (!related) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
// When checking for comparability, be more lenient with optional properties.
|
||||
if (relation !== comparableRelation && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
|
||||
// TypeScript 1.0 spec (April 2014): 3.8.3
|
||||
// S is a subtype of a type T, and T is a supertype of S if ...
|
||||
// S' and T are object types and, for each member M in T..
|
||||
// M is a property and S' contains a property N where
|
||||
// if M is a required property, N is also a required property
|
||||
// (M - property in T)
|
||||
// (N - property in S)
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2,
|
||||
symbolToString(targetProp), typeToString(source), typeToString(target));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
return related;
|
||||
}
|
||||
|
||||
function propertiesRelatedTo(source: Type, target: Type, reportErrors: boolean, excludedProperties: UnderscoreEscapedMap<true> | undefined): Ternary {
|
||||
if (relation === identityRelation) {
|
||||
return propertiesIdenticalTo(source, target);
|
||||
return propertiesIdenticalTo(source, target, excludedProperties);
|
||||
}
|
||||
const requireOptionalProperties = relation === subtypeRelation && !isObjectLiteralType(source) && !isEmptyArrayLiteralType(source) && !isTupleType(source);
|
||||
const unmatchedProperty = getUnmatchedProperty(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false);
|
||||
|
@ -13288,7 +13477,7 @@ namespace ts {
|
|||
return Ternary.False;
|
||||
}
|
||||
if (isObjectLiteralType(target)) {
|
||||
for (const sourceProp of getPropertiesOfType(source)) {
|
||||
for (const sourceProp of excludeProperties(getPropertiesOfType(source), excludedProperties)) {
|
||||
if (!getPropertyOfObjectType(target, sourceProp.escapedName)) {
|
||||
const sourceType = getTypeOfSymbol(sourceProp);
|
||||
if (!(sourceType === undefinedType || sourceType === undefinedWideningType)) {
|
||||
|
@ -13331,89 +13520,30 @@ namespace ts {
|
|||
// We only call this for union target types when we're attempting to do excess property checking - in those cases, we want to get _all possible props_
|
||||
// from the target union, across all members
|
||||
const properties = target.flags & TypeFlags.Union ? getPossiblePropertiesOfUnionType(target as UnionType) : getPropertiesOfType(target);
|
||||
for (const targetProp of properties) {
|
||||
for (const targetProp of excludeProperties(properties, excludedProperties)) {
|
||||
if (!(targetProp.flags & SymbolFlags.Prototype)) {
|
||||
const sourceProp = getPropertyOfType(source, targetProp.escapedName);
|
||||
if (sourceProp && sourceProp !== targetProp) {
|
||||
if (isIgnoredJsxProperty(source, sourceProp, getTypeOfSymbol(targetProp))) {
|
||||
continue;
|
||||
}
|
||||
const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp);
|
||||
const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp);
|
||||
if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) {
|
||||
const hasDifferingDeclarations = sourceProp.valueDeclaration !== targetProp.valueDeclaration;
|
||||
if (getCheckFlags(sourceProp) & CheckFlags.ContainsPrivate && hasDifferingDeclarations) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Property_0_has_conflicting_declarations_and_is_inaccessible_in_type_1, symbolToString(sourceProp), typeToString(source));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
if (hasDifferingDeclarations) {
|
||||
if (reportErrors) {
|
||||
if (sourcePropFlags & ModifierFlags.Private && targetPropFlags & ModifierFlags.Private) {
|
||||
reportError(Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp));
|
||||
}
|
||||
else {
|
||||
reportError(Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp),
|
||||
typeToString(sourcePropFlags & ModifierFlags.Private ? source : target),
|
||||
typeToString(sourcePropFlags & ModifierFlags.Private ? target : source));
|
||||
}
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
else if (targetPropFlags & ModifierFlags.Protected) {
|
||||
if (!isValidOverrideOf(sourceProp, targetProp)) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, symbolToString(targetProp),
|
||||
typeToString(getDeclaringClass(sourceProp) || source), typeToString(getDeclaringClass(targetProp) || target));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
else if (sourcePropFlags & ModifierFlags.Protected) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2,
|
||||
symbolToString(targetProp), typeToString(source), typeToString(target));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
// If the target comes from a partial union prop, allow `undefined` in the target type
|
||||
const related = isRelatedTo(getTypeOfSymbol(sourceProp), addOptionality(getTypeOfSymbol(targetProp), !!(getCheckFlags(targetProp) & CheckFlags.Partial)), reportErrors);
|
||||
const related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors);
|
||||
if (!related) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
result &= related;
|
||||
// When checking for comparability, be more lenient with optional properties.
|
||||
if (relation !== comparableRelation && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
|
||||
// TypeScript 1.0 spec (April 2014): 3.8.3
|
||||
// S is a subtype of a type T, and T is a supertype of S if ...
|
||||
// S' and T are object types and, for each member M in T..
|
||||
// M is a property and S' contains a property N where
|
||||
// if M is a required property, N is also a required property
|
||||
// (M - property in T)
|
||||
// (N - property in S)
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2,
|
||||
symbolToString(targetProp), typeToString(source), typeToString(target));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function propertiesIdenticalTo(source: Type, target: Type): Ternary {
|
||||
function propertiesIdenticalTo(source: Type, target: Type, excludedProperties: UnderscoreEscapedMap<true> | undefined): Ternary {
|
||||
if (!(source.flags & TypeFlags.Object && target.flags & TypeFlags.Object)) {
|
||||
return Ternary.False;
|
||||
}
|
||||
const sourceProperties = getPropertiesOfObjectType(source);
|
||||
const targetProperties = getPropertiesOfObjectType(target);
|
||||
const sourceProperties = excludeProperties(getPropertiesOfObjectType(source), excludedProperties);
|
||||
const targetProperties = excludeProperties(getPropertiesOfObjectType(target), excludedProperties);
|
||||
if (sourceProperties.length !== targetProperties.length) {
|
||||
return Ternary.False;
|
||||
}
|
||||
|
@ -15952,6 +16082,10 @@ namespace ts {
|
|||
return f(type) ? type : neverType;
|
||||
}
|
||||
|
||||
function countTypes(type: Type) {
|
||||
return type.flags & TypeFlags.Union ? (type as UnionType).types.length : 1;
|
||||
}
|
||||
|
||||
// Apply a mapping function to a type and return the resulting type. If the source type
|
||||
// is a union type, the mapping function is applied to each constituent type and a union
|
||||
// of the resulting types is returned.
|
||||
|
|
|
@ -2284,4 +2284,29 @@ namespace ts {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function cartesianProduct<T>(arrays: readonly T[][]) {
|
||||
const result: T[][] = [];
|
||||
cartesianProductWorker(arrays, result, /*outer*/ undefined, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
function cartesianProductWorker<T>(arrays: readonly (readonly T[])[], result: (readonly T[])[], outer: readonly T[] | undefined, index: number) {
|
||||
for (const element of arrays[index]) {
|
||||
let inner: T[];
|
||||
if (outer) {
|
||||
inner = outer.slice();
|
||||
inner.push(element);
|
||||
}
|
||||
else {
|
||||
inner = [element];
|
||||
}
|
||||
if (index === arrays.length - 1) {
|
||||
result.push(inner);
|
||||
}
|
||||
else {
|
||||
cartesianProductWorker(arrays, result, inner, index + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts(44,5): error TS2322: Type 'S' is not assignable to type 'T'.
|
||||
Type 'S' is not assignable to type '{ a: 2; b: 3; }'.
|
||||
Types of property 'a' are incompatible.
|
||||
Type '0 | 2' is not assignable to type '2'.
|
||||
Type '0' is not assignable to type '2'.
|
||||
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts(58,5): error TS2322: Type 'S' is not assignable to type 'T'.
|
||||
Property 'c' is missing in type 'S' but required in type '{ a: 2; b: 4 | 3; c: string; }'.
|
||||
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts(82,5): error TS2322: Type 'S' is not assignable to type 'T'.
|
||||
Type 'S' is not assignable to type '{ a: 0 | 2 | 1; b: 0 | 2 | 1; c: 2; }'.
|
||||
Types of property 'c' are incompatible.
|
||||
Type '0 | 2 | 1' is not assignable to type '2'.
|
||||
Type '0' is not assignable to type '2'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts (3 errors) ====
|
||||
// see 'typeRelatedToDiscriminatedType' in checker.ts:
|
||||
|
||||
// IteratorResult
|
||||
namespace Example1 {
|
||||
type S = { done: boolean, value: number };
|
||||
type T =
|
||||
| { done: true, value: number } // T0
|
||||
| { done: false, value: number }; // T1
|
||||
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S is assignable to T0 when S["done"] is true
|
||||
// S is assignable to T1 when S["done"] is false
|
||||
t = s;
|
||||
}
|
||||
|
||||
// Dropping constituents of T
|
||||
namespace Example2 {
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
| { a: 1, b: 2 } // T1
|
||||
| { a: 2, b: 3 | 4 }; // T2
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is assignable to T2 when S["a"] is 2
|
||||
t = s;
|
||||
}
|
||||
|
||||
// Unmatched discriminants
|
||||
namespace Example3 {
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
| { a: 1, b: 2 | 4 } // T1
|
||||
| { a: 2, b: 3 }; // T2
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is *not* assignable to T1 when S["b"] is 4
|
||||
// S is *not* assignable to T2 when S["a"] is 2
|
||||
t = s;
|
||||
~
|
||||
!!! error TS2322: Type 'S' is not assignable to type 'T'.
|
||||
!!! error TS2322: Type 'S' is not assignable to type '{ a: 2; b: 3; }'.
|
||||
!!! error TS2322: Types of property 'a' are incompatible.
|
||||
!!! error TS2322: Type '0 | 2' is not assignable to type '2'.
|
||||
!!! error TS2322: Type '0' is not assignable to type '2'.
|
||||
}
|
||||
|
||||
// Unmatched non-discriminants
|
||||
namespace Example4 {
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
| { a: 1, b: 2 } // T1
|
||||
| { a: 2, b: 3 | 4, c: string }; // T2
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is *not* assignable to T2 when S["a"] is 2 as S is missing "c"
|
||||
t = s;
|
||||
~
|
||||
!!! error TS2322: Type 'S' is not assignable to type 'T'.
|
||||
!!! error TS2322: Property 'c' is missing in type 'S' but required in type '{ a: 2; b: 4 | 3; c: string; }'.
|
||||
!!! related TS2728 tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts:52:36: 'c' is declared here.
|
||||
}
|
||||
|
||||
// Maximum discriminant combinations
|
||||
namespace Example5 {
|
||||
// NOTE: The maximum number of discriminant type combinations is currently 25.
|
||||
// 3 discriminant properties with 3 types a piece
|
||||
// is 27 possible combinations.
|
||||
type N = 0 | 1 | 2;
|
||||
type S = { a: N, b: N, c: N };
|
||||
type T = { a: 0, b: N, c: N }
|
||||
| { a: 1, b: N, c: N }
|
||||
| { a: 2, b: N, c: N }
|
||||
| { a: N, b: 0, c: N }
|
||||
| { a: N, b: 1, c: N }
|
||||
| { a: N, b: 2, c: N }
|
||||
| { a: N, b: N, c: 0 }
|
||||
| { a: N, b: N, c: 1 }
|
||||
| { a: N, b: N, c: 2 };
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S *should* be assignable but the number of
|
||||
// combinations is too complex.
|
||||
t = s;
|
||||
~
|
||||
!!! error TS2322: Type 'S' is not assignable to type 'T'.
|
||||
!!! error TS2322: Type 'S' is not assignable to type '{ a: 0 | 2 | 1; b: 0 | 2 | 1; c: 2; }'.
|
||||
!!! error TS2322: Types of property 'c' are incompatible.
|
||||
!!! error TS2322: Type '0 | 2 | 1' is not assignable to type '2'.
|
||||
!!! error TS2322: Type '0' is not assignable to type '2'.
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/14865
|
||||
namespace GH14865 {
|
||||
type Style1 = {
|
||||
type: "A";
|
||||
data: string;
|
||||
} | {
|
||||
type: "B";
|
||||
data: string;
|
||||
};
|
||||
|
||||
type Style2 = {
|
||||
type: "A" | "B";
|
||||
data: string;
|
||||
}
|
||||
|
||||
const a: Style2 = { type: "A", data: "whatevs" };
|
||||
let b: Style1;
|
||||
a.type; // "A" | "B"
|
||||
b.type; // "A" | "B"
|
||||
b = a; // should be assignable
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/30170
|
||||
namespace GH30170 {
|
||||
interface Blue {
|
||||
color: 'blue'
|
||||
}
|
||||
interface Yellow {
|
||||
color?: 'yellow',
|
||||
}
|
||||
function draw(val: Blue | Yellow) { }
|
||||
|
||||
function drawWithColor(currentColor: 'blue' | 'yellow' | undefined) {
|
||||
return draw({ color: currentColor });
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/12052
|
||||
namespace GH12052 {
|
||||
interface ILinearAxis { type: "linear"; }
|
||||
|
||||
interface ICategoricalAxis { type: "categorical"; }
|
||||
|
||||
type IAxis = ILinearAxis | ICategoricalAxis;
|
||||
type IAxisType = "linear" | "categorical";
|
||||
|
||||
function getAxisType(): IAxisType {
|
||||
if (1 == 1) {
|
||||
return "categorical";
|
||||
} else {
|
||||
return "linear";
|
||||
}
|
||||
}
|
||||
|
||||
const bad: IAxis = { type: getAxisType() };
|
||||
const good: IAxis = { type: undefined };
|
||||
good.type = getAxisType();
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/18421
|
||||
namespace GH18421 {
|
||||
interface ThingTypeOne {
|
||||
type: 'one';
|
||||
}
|
||||
|
||||
interface ThingTypeTwo {
|
||||
type: 'two';
|
||||
}
|
||||
|
||||
type ThingType = 'one' | 'two';
|
||||
|
||||
type Thing = ThingTypeOne | ThingTypeTwo;
|
||||
|
||||
function makeNewThing(thingType: ThingType): Thing {
|
||||
return {
|
||||
type: thingType
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/15907
|
||||
namespace GH15907 {
|
||||
type Action = { type: 'activate' } | { type: 'disactivate' };
|
||||
|
||||
function dispatchAction(action: Action): void {
|
||||
|
||||
}
|
||||
|
||||
const active = true;
|
||||
|
||||
dispatchAction({ type : (active? 'disactivate' : 'activate') });
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/20889
|
||||
namespace GH20889 {
|
||||
interface A1 {
|
||||
type: "A1";
|
||||
}
|
||||
interface A2 {
|
||||
type: "A2";
|
||||
}
|
||||
type AU = A1 | A2;
|
||||
|
||||
function foo(obj1: AU) {
|
||||
const obj2: AU = {
|
||||
type: obj1.type
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,291 @@
|
|||
//// [assignmentCompatWithDiscriminatedUnion.ts]
|
||||
// see 'typeRelatedToDiscriminatedType' in checker.ts:
|
||||
|
||||
// IteratorResult
|
||||
namespace Example1 {
|
||||
type S = { done: boolean, value: number };
|
||||
type T =
|
||||
| { done: true, value: number } // T0
|
||||
| { done: false, value: number }; // T1
|
||||
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S is assignable to T0 when S["done"] is true
|
||||
// S is assignable to T1 when S["done"] is false
|
||||
t = s;
|
||||
}
|
||||
|
||||
// Dropping constituents of T
|
||||
namespace Example2 {
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
| { a: 1, b: 2 } // T1
|
||||
| { a: 2, b: 3 | 4 }; // T2
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is assignable to T2 when S["a"] is 2
|
||||
t = s;
|
||||
}
|
||||
|
||||
// Unmatched discriminants
|
||||
namespace Example3 {
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
| { a: 1, b: 2 | 4 } // T1
|
||||
| { a: 2, b: 3 }; // T2
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is *not* assignable to T1 when S["b"] is 4
|
||||
// S is *not* assignable to T2 when S["a"] is 2
|
||||
t = s;
|
||||
}
|
||||
|
||||
// Unmatched non-discriminants
|
||||
namespace Example4 {
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
| { a: 1, b: 2 } // T1
|
||||
| { a: 2, b: 3 | 4, c: string }; // T2
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is *not* assignable to T2 when S["a"] is 2 as S is missing "c"
|
||||
t = s;
|
||||
}
|
||||
|
||||
// Maximum discriminant combinations
|
||||
namespace Example5 {
|
||||
// NOTE: The maximum number of discriminant type combinations is currently 25.
|
||||
// 3 discriminant properties with 3 types a piece
|
||||
// is 27 possible combinations.
|
||||
type N = 0 | 1 | 2;
|
||||
type S = { a: N, b: N, c: N };
|
||||
type T = { a: 0, b: N, c: N }
|
||||
| { a: 1, b: N, c: N }
|
||||
| { a: 2, b: N, c: N }
|
||||
| { a: N, b: 0, c: N }
|
||||
| { a: N, b: 1, c: N }
|
||||
| { a: N, b: 2, c: N }
|
||||
| { a: N, b: N, c: 0 }
|
||||
| { a: N, b: N, c: 1 }
|
||||
| { a: N, b: N, c: 2 };
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S *should* be assignable but the number of
|
||||
// combinations is too complex.
|
||||
t = s;
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/14865
|
||||
namespace GH14865 {
|
||||
type Style1 = {
|
||||
type: "A";
|
||||
data: string;
|
||||
} | {
|
||||
type: "B";
|
||||
data: string;
|
||||
};
|
||||
|
||||
type Style2 = {
|
||||
type: "A" | "B";
|
||||
data: string;
|
||||
}
|
||||
|
||||
const a: Style2 = { type: "A", data: "whatevs" };
|
||||
let b: Style1;
|
||||
a.type; // "A" | "B"
|
||||
b.type; // "A" | "B"
|
||||
b = a; // should be assignable
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/30170
|
||||
namespace GH30170 {
|
||||
interface Blue {
|
||||
color: 'blue'
|
||||
}
|
||||
interface Yellow {
|
||||
color?: 'yellow',
|
||||
}
|
||||
function draw(val: Blue | Yellow) { }
|
||||
|
||||
function drawWithColor(currentColor: 'blue' | 'yellow' | undefined) {
|
||||
return draw({ color: currentColor });
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/12052
|
||||
namespace GH12052 {
|
||||
interface ILinearAxis { type: "linear"; }
|
||||
|
||||
interface ICategoricalAxis { type: "categorical"; }
|
||||
|
||||
type IAxis = ILinearAxis | ICategoricalAxis;
|
||||
type IAxisType = "linear" | "categorical";
|
||||
|
||||
function getAxisType(): IAxisType {
|
||||
if (1 == 1) {
|
||||
return "categorical";
|
||||
} else {
|
||||
return "linear";
|
||||
}
|
||||
}
|
||||
|
||||
const bad: IAxis = { type: getAxisType() };
|
||||
const good: IAxis = { type: undefined };
|
||||
good.type = getAxisType();
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/18421
|
||||
namespace GH18421 {
|
||||
interface ThingTypeOne {
|
||||
type: 'one';
|
||||
}
|
||||
|
||||
interface ThingTypeTwo {
|
||||
type: 'two';
|
||||
}
|
||||
|
||||
type ThingType = 'one' | 'two';
|
||||
|
||||
type Thing = ThingTypeOne | ThingTypeTwo;
|
||||
|
||||
function makeNewThing(thingType: ThingType): Thing {
|
||||
return {
|
||||
type: thingType
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/15907
|
||||
namespace GH15907 {
|
||||
type Action = { type: 'activate' } | { type: 'disactivate' };
|
||||
|
||||
function dispatchAction(action: Action): void {
|
||||
|
||||
}
|
||||
|
||||
const active = true;
|
||||
|
||||
dispatchAction({ type : (active? 'disactivate' : 'activate') });
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/20889
|
||||
namespace GH20889 {
|
||||
interface A1 {
|
||||
type: "A1";
|
||||
}
|
||||
interface A2 {
|
||||
type: "A2";
|
||||
}
|
||||
type AU = A1 | A2;
|
||||
|
||||
function foo(obj1: AU) {
|
||||
const obj2: AU = {
|
||||
type: obj1.type
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//// [assignmentCompatWithDiscriminatedUnion.js]
|
||||
// see 'typeRelatedToDiscriminatedType' in checker.ts:
|
||||
// IteratorResult
|
||||
var Example1;
|
||||
(function (Example1) {
|
||||
// S is assignable to T0 when S["done"] is true
|
||||
// S is assignable to T1 when S["done"] is false
|
||||
t = s;
|
||||
})(Example1 || (Example1 = {}));
|
||||
// Dropping constituents of T
|
||||
var Example2;
|
||||
(function (Example2) {
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is assignable to T2 when S["a"] is 2
|
||||
t = s;
|
||||
})(Example2 || (Example2 = {}));
|
||||
// Unmatched discriminants
|
||||
var Example3;
|
||||
(function (Example3) {
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is *not* assignable to T1 when S["b"] is 4
|
||||
// S is *not* assignable to T2 when S["a"] is 2
|
||||
t = s;
|
||||
})(Example3 || (Example3 = {}));
|
||||
// Unmatched non-discriminants
|
||||
var Example4;
|
||||
(function (Example4) {
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is *not* assignable to T2 when S["a"] is 2 as S is missing "c"
|
||||
t = s;
|
||||
})(Example4 || (Example4 = {}));
|
||||
// Maximum discriminant combinations
|
||||
var Example5;
|
||||
(function (Example5) {
|
||||
// S *should* be assignable but the number of
|
||||
// combinations is too complex.
|
||||
t = s;
|
||||
})(Example5 || (Example5 = {}));
|
||||
// https://github.com/Microsoft/TypeScript/issues/14865
|
||||
var GH14865;
|
||||
(function (GH14865) {
|
||||
var a = { type: "A", data: "whatevs" };
|
||||
var b;
|
||||
a.type; // "A" | "B"
|
||||
b.type; // "A" | "B"
|
||||
b = a; // should be assignable
|
||||
})(GH14865 || (GH14865 = {}));
|
||||
// https://github.com/Microsoft/TypeScript/issues/30170
|
||||
var GH30170;
|
||||
(function (GH30170) {
|
||||
function draw(val) { }
|
||||
function drawWithColor(currentColor) {
|
||||
return draw({ color: currentColor });
|
||||
}
|
||||
})(GH30170 || (GH30170 = {}));
|
||||
// https://github.com/Microsoft/TypeScript/issues/12052
|
||||
var GH12052;
|
||||
(function (GH12052) {
|
||||
function getAxisType() {
|
||||
if (1 == 1) {
|
||||
return "categorical";
|
||||
}
|
||||
else {
|
||||
return "linear";
|
||||
}
|
||||
}
|
||||
var bad = { type: getAxisType() };
|
||||
var good = { type: undefined };
|
||||
good.type = getAxisType();
|
||||
})(GH12052 || (GH12052 = {}));
|
||||
// https://github.com/Microsoft/TypeScript/issues/18421
|
||||
var GH18421;
|
||||
(function (GH18421) {
|
||||
function makeNewThing(thingType) {
|
||||
return {
|
||||
type: thingType
|
||||
};
|
||||
}
|
||||
})(GH18421 || (GH18421 = {}));
|
||||
// https://github.com/Microsoft/TypeScript/issues/15907
|
||||
var GH15907;
|
||||
(function (GH15907) {
|
||||
function dispatchAction(action) {
|
||||
}
|
||||
var active = true;
|
||||
dispatchAction({ type: (active ? 'disactivate' : 'activate') });
|
||||
})(GH15907 || (GH15907 = {}));
|
||||
// https://github.com/Microsoft/TypeScript/issues/20889
|
||||
var GH20889;
|
||||
(function (GH20889) {
|
||||
function foo(obj1) {
|
||||
var obj2 = {
|
||||
type: obj1.type
|
||||
};
|
||||
}
|
||||
})(GH20889 || (GH20889 = {}));
|
|
@ -0,0 +1,494 @@
|
|||
=== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts ===
|
||||
// see 'typeRelatedToDiscriminatedType' in checker.ts:
|
||||
|
||||
// IteratorResult
|
||||
namespace Example1 {
|
||||
>Example1 : Symbol(Example1, Decl(assignmentCompatWithDiscriminatedUnion.ts, 0, 0))
|
||||
|
||||
type S = { done: boolean, value: number };
|
||||
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 3, 20))
|
||||
>done : Symbol(done, Decl(assignmentCompatWithDiscriminatedUnion.ts, 4, 14))
|
||||
>value : Symbol(value, Decl(assignmentCompatWithDiscriminatedUnion.ts, 4, 29))
|
||||
|
||||
type T =
|
||||
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 4, 46))
|
||||
|
||||
| { done: true, value: number } // T0
|
||||
>done : Symbol(done, Decl(assignmentCompatWithDiscriminatedUnion.ts, 6, 11))
|
||||
>value : Symbol(value, Decl(assignmentCompatWithDiscriminatedUnion.ts, 6, 23))
|
||||
|
||||
| { done: false, value: number }; // T1
|
||||
>done : Symbol(done, Decl(assignmentCompatWithDiscriminatedUnion.ts, 7, 11))
|
||||
>value : Symbol(value, Decl(assignmentCompatWithDiscriminatedUnion.ts, 7, 24))
|
||||
|
||||
declare let s: S;
|
||||
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 9, 15))
|
||||
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 3, 20))
|
||||
|
||||
declare let t: T;
|
||||
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 10, 15))
|
||||
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 4, 46))
|
||||
|
||||
// S is assignable to T0 when S["done"] is true
|
||||
// S is assignable to T1 when S["done"] is false
|
||||
t = s;
|
||||
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 10, 15))
|
||||
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 9, 15))
|
||||
}
|
||||
|
||||
// Dropping constituents of T
|
||||
namespace Example2 {
|
||||
>Example2 : Symbol(Example2, Decl(assignmentCompatWithDiscriminatedUnion.ts, 15, 1))
|
||||
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 18, 20))
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 19, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 19, 24))
|
||||
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 19, 32))
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 20, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 20, 20))
|
||||
|
||||
| { a: 1, b: 2 } // T1
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 21, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 21, 20))
|
||||
|
||||
| { a: 2, b: 3 | 4 }; // T2
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 22, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 22, 20))
|
||||
|
||||
declare let s: S;
|
||||
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 23, 15))
|
||||
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 18, 20))
|
||||
|
||||
declare let t: T;
|
||||
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 24, 15))
|
||||
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 19, 32))
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is assignable to T2 when S["a"] is 2
|
||||
t = s;
|
||||
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 24, 15))
|
||||
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 23, 15))
|
||||
}
|
||||
|
||||
// Unmatched discriminants
|
||||
namespace Example3 {
|
||||
>Example3 : Symbol(Example3, Decl(assignmentCompatWithDiscriminatedUnion.ts, 29, 1))
|
||||
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 32, 20))
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 33, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 33, 24))
|
||||
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 33, 32))
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 34, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 34, 20))
|
||||
|
||||
| { a: 1, b: 2 | 4 } // T1
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 35, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 35, 20))
|
||||
|
||||
| { a: 2, b: 3 }; // T2
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 36, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 36, 20))
|
||||
|
||||
declare let s: S;
|
||||
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 37, 15))
|
||||
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 32, 20))
|
||||
|
||||
declare let t: T;
|
||||
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 38, 15))
|
||||
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 33, 32))
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is *not* assignable to T1 when S["b"] is 4
|
||||
// S is *not* assignable to T2 when S["a"] is 2
|
||||
t = s;
|
||||
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 38, 15))
|
||||
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 37, 15))
|
||||
}
|
||||
|
||||
// Unmatched non-discriminants
|
||||
namespace Example4 {
|
||||
>Example4 : Symbol(Example4, Decl(assignmentCompatWithDiscriminatedUnion.ts, 44, 1))
|
||||
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 47, 20))
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 48, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 48, 24))
|
||||
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 48, 32))
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 49, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 49, 20))
|
||||
|
||||
| { a: 1, b: 2 } // T1
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 50, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 50, 20))
|
||||
|
||||
| { a: 2, b: 3 | 4, c: string }; // T2
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 51, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 51, 20))
|
||||
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 51, 34))
|
||||
|
||||
declare let s: S;
|
||||
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 52, 15))
|
||||
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 47, 20))
|
||||
|
||||
declare let t: T;
|
||||
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 53, 15))
|
||||
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 48, 32))
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is *not* assignable to T2 when S["a"] is 2 as S is missing "c"
|
||||
t = s;
|
||||
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 53, 15))
|
||||
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 52, 15))
|
||||
}
|
||||
|
||||
// Maximum discriminant combinations
|
||||
namespace Example5 {
|
||||
>Example5 : Symbol(Example5, Decl(assignmentCompatWithDiscriminatedUnion.ts, 58, 1))
|
||||
|
||||
// NOTE: The maximum number of discriminant type combinations is currently 25.
|
||||
// 3 discriminant properties with 3 types a piece
|
||||
// is 27 possible combinations.
|
||||
type N = 0 | 1 | 2;
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
|
||||
type S = { a: N, b: N, c: N };
|
||||
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 65, 23))
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 66, 14))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 66, 20))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 66, 26))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
|
||||
type T = { a: 0, b: N, c: N }
|
||||
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 66, 34))
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 67, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 67, 20))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 67, 26))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
|
||||
| { a: 1, b: N, c: N }
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 68, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 68, 20))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 68, 26))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
|
||||
| { a: 2, b: N, c: N }
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 69, 14))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 69, 20))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 69, 26))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
|
||||
| { a: N, b: 0, c: N }
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 70, 14))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 70, 20))
|
||||
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 70, 26))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
|
||||
| { a: N, b: 1, c: N }
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 71, 14))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 71, 20))
|
||||
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 71, 26))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
|
||||
| { a: N, b: 2, c: N }
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 72, 14))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 72, 20))
|
||||
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 72, 26))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
|
||||
| { a: N, b: N, c: 0 }
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 73, 14))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 73, 20))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 73, 26))
|
||||
|
||||
| { a: N, b: N, c: 1 }
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 74, 14))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 74, 20))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 74, 26))
|
||||
|
||||
| { a: N, b: N, c: 2 };
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 75, 14))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 75, 20))
|
||||
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
|
||||
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 75, 26))
|
||||
|
||||
declare let s: S;
|
||||
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 76, 15))
|
||||
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 65, 23))
|
||||
|
||||
declare let t: T;
|
||||
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 77, 15))
|
||||
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 66, 34))
|
||||
|
||||
// S *should* be assignable but the number of
|
||||
// combinations is too complex.
|
||||
t = s;
|
||||
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 77, 15))
|
||||
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 76, 15))
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/14865
|
||||
namespace GH14865 {
|
||||
>GH14865 : Symbol(GH14865, Decl(assignmentCompatWithDiscriminatedUnion.ts, 82, 1))
|
||||
|
||||
type Style1 = {
|
||||
>Style1 : Symbol(Style1, Decl(assignmentCompatWithDiscriminatedUnion.ts, 85, 19))
|
||||
|
||||
type: "A";
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 86, 19))
|
||||
|
||||
data: string;
|
||||
>data : Symbol(data, Decl(assignmentCompatWithDiscriminatedUnion.ts, 87, 18))
|
||||
|
||||
} | {
|
||||
type: "B";
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 89, 9))
|
||||
|
||||
data: string;
|
||||
>data : Symbol(data, Decl(assignmentCompatWithDiscriminatedUnion.ts, 90, 18))
|
||||
|
||||
};
|
||||
|
||||
type Style2 = {
|
||||
>Style2 : Symbol(Style2, Decl(assignmentCompatWithDiscriminatedUnion.ts, 92, 6))
|
||||
|
||||
type: "A" | "B";
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 94, 19))
|
||||
|
||||
data: string;
|
||||
>data : Symbol(data, Decl(assignmentCompatWithDiscriminatedUnion.ts, 95, 24))
|
||||
}
|
||||
|
||||
const a: Style2 = { type: "A", data: "whatevs" };
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 99, 9))
|
||||
>Style2 : Symbol(Style2, Decl(assignmentCompatWithDiscriminatedUnion.ts, 92, 6))
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 99, 23))
|
||||
>data : Symbol(data, Decl(assignmentCompatWithDiscriminatedUnion.ts, 99, 34))
|
||||
|
||||
let b: Style1;
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 100, 7))
|
||||
>Style1 : Symbol(Style1, Decl(assignmentCompatWithDiscriminatedUnion.ts, 85, 19))
|
||||
|
||||
a.type; // "A" | "B"
|
||||
>a.type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 94, 19))
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 99, 9))
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 94, 19))
|
||||
|
||||
b.type; // "A" | "B"
|
||||
>b.type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 86, 19), Decl(assignmentCompatWithDiscriminatedUnion.ts, 89, 9))
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 100, 7))
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 86, 19), Decl(assignmentCompatWithDiscriminatedUnion.ts, 89, 9))
|
||||
|
||||
b = a; // should be assignable
|
||||
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 100, 7))
|
||||
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 99, 9))
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/30170
|
||||
namespace GH30170 {
|
||||
>GH30170 : Symbol(GH30170, Decl(assignmentCompatWithDiscriminatedUnion.ts, 104, 1))
|
||||
|
||||
interface Blue {
|
||||
>Blue : Symbol(Blue, Decl(assignmentCompatWithDiscriminatedUnion.ts, 107, 19))
|
||||
|
||||
color: 'blue'
|
||||
>color : Symbol(Blue.color, Decl(assignmentCompatWithDiscriminatedUnion.ts, 108, 20))
|
||||
}
|
||||
interface Yellow {
|
||||
>Yellow : Symbol(Yellow, Decl(assignmentCompatWithDiscriminatedUnion.ts, 110, 5))
|
||||
|
||||
color?: 'yellow',
|
||||
>color : Symbol(Yellow.color, Decl(assignmentCompatWithDiscriminatedUnion.ts, 111, 22))
|
||||
}
|
||||
function draw(val: Blue | Yellow) { }
|
||||
>draw : Symbol(draw, Decl(assignmentCompatWithDiscriminatedUnion.ts, 113, 5))
|
||||
>val : Symbol(val, Decl(assignmentCompatWithDiscriminatedUnion.ts, 114, 18))
|
||||
>Blue : Symbol(Blue, Decl(assignmentCompatWithDiscriminatedUnion.ts, 107, 19))
|
||||
>Yellow : Symbol(Yellow, Decl(assignmentCompatWithDiscriminatedUnion.ts, 110, 5))
|
||||
|
||||
function drawWithColor(currentColor: 'blue' | 'yellow' | undefined) {
|
||||
>drawWithColor : Symbol(drawWithColor, Decl(assignmentCompatWithDiscriminatedUnion.ts, 114, 41))
|
||||
>currentColor : Symbol(currentColor, Decl(assignmentCompatWithDiscriminatedUnion.ts, 116, 27))
|
||||
|
||||
return draw({ color: currentColor });
|
||||
>draw : Symbol(draw, Decl(assignmentCompatWithDiscriminatedUnion.ts, 113, 5))
|
||||
>color : Symbol(color, Decl(assignmentCompatWithDiscriminatedUnion.ts, 117, 21))
|
||||
>currentColor : Symbol(currentColor, Decl(assignmentCompatWithDiscriminatedUnion.ts, 116, 27))
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/12052
|
||||
namespace GH12052 {
|
||||
>GH12052 : Symbol(GH12052, Decl(assignmentCompatWithDiscriminatedUnion.ts, 119, 1))
|
||||
|
||||
interface ILinearAxis { type: "linear"; }
|
||||
>ILinearAxis : Symbol(ILinearAxis, Decl(assignmentCompatWithDiscriminatedUnion.ts, 122, 19))
|
||||
>type : Symbol(ILinearAxis.type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 123, 27))
|
||||
|
||||
interface ICategoricalAxis { type: "categorical"; }
|
||||
>ICategoricalAxis : Symbol(ICategoricalAxis, Decl(assignmentCompatWithDiscriminatedUnion.ts, 123, 45))
|
||||
>type : Symbol(ICategoricalAxis.type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 125, 32))
|
||||
|
||||
type IAxis = ILinearAxis | ICategoricalAxis;
|
||||
>IAxis : Symbol(IAxis, Decl(assignmentCompatWithDiscriminatedUnion.ts, 125, 55))
|
||||
>ILinearAxis : Symbol(ILinearAxis, Decl(assignmentCompatWithDiscriminatedUnion.ts, 122, 19))
|
||||
>ICategoricalAxis : Symbol(ICategoricalAxis, Decl(assignmentCompatWithDiscriminatedUnion.ts, 123, 45))
|
||||
|
||||
type IAxisType = "linear" | "categorical";
|
||||
>IAxisType : Symbol(IAxisType, Decl(assignmentCompatWithDiscriminatedUnion.ts, 127, 48))
|
||||
|
||||
function getAxisType(): IAxisType {
|
||||
>getAxisType : Symbol(getAxisType, Decl(assignmentCompatWithDiscriminatedUnion.ts, 128, 46))
|
||||
>IAxisType : Symbol(IAxisType, Decl(assignmentCompatWithDiscriminatedUnion.ts, 127, 48))
|
||||
|
||||
if (1 == 1) {
|
||||
return "categorical";
|
||||
} else {
|
||||
return "linear";
|
||||
}
|
||||
}
|
||||
|
||||
const bad: IAxis = { type: getAxisType() };
|
||||
>bad : Symbol(bad, Decl(assignmentCompatWithDiscriminatedUnion.ts, 138, 9))
|
||||
>IAxis : Symbol(IAxis, Decl(assignmentCompatWithDiscriminatedUnion.ts, 125, 55))
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 138, 24))
|
||||
>getAxisType : Symbol(getAxisType, Decl(assignmentCompatWithDiscriminatedUnion.ts, 128, 46))
|
||||
|
||||
const good: IAxis = { type: undefined };
|
||||
>good : Symbol(good, Decl(assignmentCompatWithDiscriminatedUnion.ts, 139, 9))
|
||||
>IAxis : Symbol(IAxis, Decl(assignmentCompatWithDiscriminatedUnion.ts, 125, 55))
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 139, 25))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
good.type = getAxisType();
|
||||
>good.type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 123, 27), Decl(assignmentCompatWithDiscriminatedUnion.ts, 125, 32))
|
||||
>good : Symbol(good, Decl(assignmentCompatWithDiscriminatedUnion.ts, 139, 9))
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 123, 27), Decl(assignmentCompatWithDiscriminatedUnion.ts, 125, 32))
|
||||
>getAxisType : Symbol(getAxisType, Decl(assignmentCompatWithDiscriminatedUnion.ts, 128, 46))
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/18421
|
||||
namespace GH18421 {
|
||||
>GH18421 : Symbol(GH18421, Decl(assignmentCompatWithDiscriminatedUnion.ts, 141, 1))
|
||||
|
||||
interface ThingTypeOne {
|
||||
>ThingTypeOne : Symbol(ThingTypeOne, Decl(assignmentCompatWithDiscriminatedUnion.ts, 144, 19))
|
||||
|
||||
type: 'one';
|
||||
>type : Symbol(ThingTypeOne.type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 145, 28))
|
||||
}
|
||||
|
||||
interface ThingTypeTwo {
|
||||
>ThingTypeTwo : Symbol(ThingTypeTwo, Decl(assignmentCompatWithDiscriminatedUnion.ts, 147, 5))
|
||||
|
||||
type: 'two';
|
||||
>type : Symbol(ThingTypeTwo.type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 149, 28))
|
||||
}
|
||||
|
||||
type ThingType = 'one' | 'two';
|
||||
>ThingType : Symbol(ThingType, Decl(assignmentCompatWithDiscriminatedUnion.ts, 151, 5))
|
||||
|
||||
type Thing = ThingTypeOne | ThingTypeTwo;
|
||||
>Thing : Symbol(Thing, Decl(assignmentCompatWithDiscriminatedUnion.ts, 153, 35))
|
||||
>ThingTypeOne : Symbol(ThingTypeOne, Decl(assignmentCompatWithDiscriminatedUnion.ts, 144, 19))
|
||||
>ThingTypeTwo : Symbol(ThingTypeTwo, Decl(assignmentCompatWithDiscriminatedUnion.ts, 147, 5))
|
||||
|
||||
function makeNewThing(thingType: ThingType): Thing {
|
||||
>makeNewThing : Symbol(makeNewThing, Decl(assignmentCompatWithDiscriminatedUnion.ts, 155, 45))
|
||||
>thingType : Symbol(thingType, Decl(assignmentCompatWithDiscriminatedUnion.ts, 157, 26))
|
||||
>ThingType : Symbol(ThingType, Decl(assignmentCompatWithDiscriminatedUnion.ts, 151, 5))
|
||||
>Thing : Symbol(Thing, Decl(assignmentCompatWithDiscriminatedUnion.ts, 153, 35))
|
||||
|
||||
return {
|
||||
type: thingType
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 158, 16))
|
||||
>thingType : Symbol(thingType, Decl(assignmentCompatWithDiscriminatedUnion.ts, 157, 26))
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/15907
|
||||
namespace GH15907 {
|
||||
>GH15907 : Symbol(GH15907, Decl(assignmentCompatWithDiscriminatedUnion.ts, 162, 1))
|
||||
|
||||
type Action = { type: 'activate' } | { type: 'disactivate' };
|
||||
>Action : Symbol(Action, Decl(assignmentCompatWithDiscriminatedUnion.ts, 165, 19))
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 166, 19))
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 166, 42))
|
||||
|
||||
function dispatchAction(action: Action): void {
|
||||
>dispatchAction : Symbol(dispatchAction, Decl(assignmentCompatWithDiscriminatedUnion.ts, 166, 65))
|
||||
>action : Symbol(action, Decl(assignmentCompatWithDiscriminatedUnion.ts, 168, 28))
|
||||
>Action : Symbol(Action, Decl(assignmentCompatWithDiscriminatedUnion.ts, 165, 19))
|
||||
|
||||
}
|
||||
|
||||
const active = true;
|
||||
>active : Symbol(active, Decl(assignmentCompatWithDiscriminatedUnion.ts, 172, 9))
|
||||
|
||||
dispatchAction({ type : (active? 'disactivate' : 'activate') });
|
||||
>dispatchAction : Symbol(dispatchAction, Decl(assignmentCompatWithDiscriminatedUnion.ts, 166, 65))
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 174, 20))
|
||||
>active : Symbol(active, Decl(assignmentCompatWithDiscriminatedUnion.ts, 172, 9))
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/20889
|
||||
namespace GH20889 {
|
||||
>GH20889 : Symbol(GH20889, Decl(assignmentCompatWithDiscriminatedUnion.ts, 175, 1))
|
||||
|
||||
interface A1 {
|
||||
>A1 : Symbol(A1, Decl(assignmentCompatWithDiscriminatedUnion.ts, 178, 19))
|
||||
|
||||
type: "A1";
|
||||
>type : Symbol(A1.type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 179, 18))
|
||||
}
|
||||
interface A2 {
|
||||
>A2 : Symbol(A2, Decl(assignmentCompatWithDiscriminatedUnion.ts, 181, 5))
|
||||
|
||||
type: "A2";
|
||||
>type : Symbol(A2.type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 182, 18))
|
||||
}
|
||||
type AU = A1 | A2;
|
||||
>AU : Symbol(AU, Decl(assignmentCompatWithDiscriminatedUnion.ts, 184, 5))
|
||||
>A1 : Symbol(A1, Decl(assignmentCompatWithDiscriminatedUnion.ts, 178, 19))
|
||||
>A2 : Symbol(A2, Decl(assignmentCompatWithDiscriminatedUnion.ts, 181, 5))
|
||||
|
||||
function foo(obj1: AU) {
|
||||
>foo : Symbol(foo, Decl(assignmentCompatWithDiscriminatedUnion.ts, 185, 22))
|
||||
>obj1 : Symbol(obj1, Decl(assignmentCompatWithDiscriminatedUnion.ts, 187, 17))
|
||||
>AU : Symbol(AU, Decl(assignmentCompatWithDiscriminatedUnion.ts, 184, 5))
|
||||
|
||||
const obj2: AU = {
|
||||
>obj2 : Symbol(obj2, Decl(assignmentCompatWithDiscriminatedUnion.ts, 188, 13))
|
||||
>AU : Symbol(AU, Decl(assignmentCompatWithDiscriminatedUnion.ts, 184, 5))
|
||||
|
||||
type: obj1.type
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 188, 26))
|
||||
>obj1.type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 179, 18), Decl(assignmentCompatWithDiscriminatedUnion.ts, 182, 18))
|
||||
>obj1 : Symbol(obj1, Decl(assignmentCompatWithDiscriminatedUnion.ts, 187, 17))
|
||||
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 179, 18), Decl(assignmentCompatWithDiscriminatedUnion.ts, 182, 18))
|
||||
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,466 @@
|
|||
=== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts ===
|
||||
// see 'typeRelatedToDiscriminatedType' in checker.ts:
|
||||
|
||||
// IteratorResult
|
||||
namespace Example1 {
|
||||
>Example1 : typeof Example1
|
||||
|
||||
type S = { done: boolean, value: number };
|
||||
>S : S
|
||||
>done : boolean
|
||||
>value : number
|
||||
|
||||
type T =
|
||||
>T : T
|
||||
|
||||
| { done: true, value: number } // T0
|
||||
>done : true
|
||||
>true : true
|
||||
>value : number
|
||||
|
||||
| { done: false, value: number }; // T1
|
||||
>done : false
|
||||
>false : false
|
||||
>value : number
|
||||
|
||||
declare let s: S;
|
||||
>s : S
|
||||
|
||||
declare let t: T;
|
||||
>t : T
|
||||
|
||||
// S is assignable to T0 when S["done"] is true
|
||||
// S is assignable to T1 when S["done"] is false
|
||||
t = s;
|
||||
>t = s : S
|
||||
>t : T
|
||||
>s : S
|
||||
}
|
||||
|
||||
// Dropping constituents of T
|
||||
namespace Example2 {
|
||||
>Example2 : typeof Example2
|
||||
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
>S : S
|
||||
>a : 0 | 2
|
||||
>b : 4
|
||||
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
>T : T
|
||||
>a : 0
|
||||
>b : 4 | 1
|
||||
|
||||
| { a: 1, b: 2 } // T1
|
||||
>a : 1
|
||||
>b : 2
|
||||
|
||||
| { a: 2, b: 3 | 4 }; // T2
|
||||
>a : 2
|
||||
>b : 4 | 3
|
||||
|
||||
declare let s: S;
|
||||
>s : S
|
||||
|
||||
declare let t: T;
|
||||
>t : T
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is assignable to T2 when S["a"] is 2
|
||||
t = s;
|
||||
>t = s : S
|
||||
>t : T
|
||||
>s : S
|
||||
}
|
||||
|
||||
// Unmatched discriminants
|
||||
namespace Example3 {
|
||||
>Example3 : typeof Example3
|
||||
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
>S : S
|
||||
>a : 0 | 2
|
||||
>b : 4
|
||||
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
>T : T
|
||||
>a : 0
|
||||
>b : 4 | 1
|
||||
|
||||
| { a: 1, b: 2 | 4 } // T1
|
||||
>a : 1
|
||||
>b : 2 | 4
|
||||
|
||||
| { a: 2, b: 3 }; // T2
|
||||
>a : 2
|
||||
>b : 3
|
||||
|
||||
declare let s: S;
|
||||
>s : S
|
||||
|
||||
declare let t: T;
|
||||
>t : T
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is *not* assignable to T1 when S["b"] is 4
|
||||
// S is *not* assignable to T2 when S["a"] is 2
|
||||
t = s;
|
||||
>t = s : S
|
||||
>t : T
|
||||
>s : S
|
||||
}
|
||||
|
||||
// Unmatched non-discriminants
|
||||
namespace Example4 {
|
||||
>Example4 : typeof Example4
|
||||
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
>S : S
|
||||
>a : 0 | 2
|
||||
>b : 4
|
||||
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
>T : T
|
||||
>a : 0
|
||||
>b : 4 | 1
|
||||
|
||||
| { a: 1, b: 2 } // T1
|
||||
>a : 1
|
||||
>b : 2
|
||||
|
||||
| { a: 2, b: 3 | 4, c: string }; // T2
|
||||
>a : 2
|
||||
>b : 4 | 3
|
||||
>c : string
|
||||
|
||||
declare let s: S;
|
||||
>s : S
|
||||
|
||||
declare let t: T;
|
||||
>t : T
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is *not* assignable to T2 when S["a"] is 2 as S is missing "c"
|
||||
t = s;
|
||||
>t = s : S
|
||||
>t : T
|
||||
>s : S
|
||||
}
|
||||
|
||||
// Maximum discriminant combinations
|
||||
namespace Example5 {
|
||||
>Example5 : typeof Example5
|
||||
|
||||
// NOTE: The maximum number of discriminant type combinations is currently 25.
|
||||
// 3 discriminant properties with 3 types a piece
|
||||
// is 27 possible combinations.
|
||||
type N = 0 | 1 | 2;
|
||||
>N : 0 | 2 | 1
|
||||
|
||||
type S = { a: N, b: N, c: N };
|
||||
>S : S
|
||||
>a : 0 | 2 | 1
|
||||
>b : 0 | 2 | 1
|
||||
>c : 0 | 2 | 1
|
||||
|
||||
type T = { a: 0, b: N, c: N }
|
||||
>T : T
|
||||
>a : 0
|
||||
>b : 0 | 2 | 1
|
||||
>c : 0 | 2 | 1
|
||||
|
||||
| { a: 1, b: N, c: N }
|
||||
>a : 1
|
||||
>b : 0 | 2 | 1
|
||||
>c : 0 | 2 | 1
|
||||
|
||||
| { a: 2, b: N, c: N }
|
||||
>a : 2
|
||||
>b : 0 | 2 | 1
|
||||
>c : 0 | 2 | 1
|
||||
|
||||
| { a: N, b: 0, c: N }
|
||||
>a : 0 | 2 | 1
|
||||
>b : 0
|
||||
>c : 0 | 2 | 1
|
||||
|
||||
| { a: N, b: 1, c: N }
|
||||
>a : 0 | 2 | 1
|
||||
>b : 1
|
||||
>c : 0 | 2 | 1
|
||||
|
||||
| { a: N, b: 2, c: N }
|
||||
>a : 0 | 2 | 1
|
||||
>b : 2
|
||||
>c : 0 | 2 | 1
|
||||
|
||||
| { a: N, b: N, c: 0 }
|
||||
>a : 0 | 2 | 1
|
||||
>b : 0 | 2 | 1
|
||||
>c : 0
|
||||
|
||||
| { a: N, b: N, c: 1 }
|
||||
>a : 0 | 2 | 1
|
||||
>b : 0 | 2 | 1
|
||||
>c : 1
|
||||
|
||||
| { a: N, b: N, c: 2 };
|
||||
>a : 0 | 2 | 1
|
||||
>b : 0 | 2 | 1
|
||||
>c : 2
|
||||
|
||||
declare let s: S;
|
||||
>s : S
|
||||
|
||||
declare let t: T;
|
||||
>t : T
|
||||
|
||||
// S *should* be assignable but the number of
|
||||
// combinations is too complex.
|
||||
t = s;
|
||||
>t = s : S
|
||||
>t : T
|
||||
>s : S
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/14865
|
||||
namespace GH14865 {
|
||||
>GH14865 : typeof GH14865
|
||||
|
||||
type Style1 = {
|
||||
>Style1 : Style1
|
||||
|
||||
type: "A";
|
||||
>type : "A"
|
||||
|
||||
data: string;
|
||||
>data : string
|
||||
|
||||
} | {
|
||||
type: "B";
|
||||
>type : "B"
|
||||
|
||||
data: string;
|
||||
>data : string
|
||||
|
||||
};
|
||||
|
||||
type Style2 = {
|
||||
>Style2 : Style2
|
||||
|
||||
type: "A" | "B";
|
||||
>type : "A" | "B"
|
||||
|
||||
data: string;
|
||||
>data : string
|
||||
}
|
||||
|
||||
const a: Style2 = { type: "A", data: "whatevs" };
|
||||
>a : Style2
|
||||
>{ type: "A", data: "whatevs" } : { type: "A"; data: string; }
|
||||
>type : "A"
|
||||
>"A" : "A"
|
||||
>data : string
|
||||
>"whatevs" : "whatevs"
|
||||
|
||||
let b: Style1;
|
||||
>b : Style1
|
||||
|
||||
a.type; // "A" | "B"
|
||||
>a.type : "A" | "B"
|
||||
>a : Style2
|
||||
>type : "A" | "B"
|
||||
|
||||
b.type; // "A" | "B"
|
||||
>b.type : "A" | "B"
|
||||
>b : Style1
|
||||
>type : "A" | "B"
|
||||
|
||||
b = a; // should be assignable
|
||||
>b = a : Style2
|
||||
>b : Style1
|
||||
>a : Style2
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/30170
|
||||
namespace GH30170 {
|
||||
>GH30170 : typeof GH30170
|
||||
|
||||
interface Blue {
|
||||
color: 'blue'
|
||||
>color : "blue"
|
||||
}
|
||||
interface Yellow {
|
||||
color?: 'yellow',
|
||||
>color : "yellow"
|
||||
}
|
||||
function draw(val: Blue | Yellow) { }
|
||||
>draw : (val: Blue | Yellow) => void
|
||||
>val : Blue | Yellow
|
||||
|
||||
function drawWithColor(currentColor: 'blue' | 'yellow' | undefined) {
|
||||
>drawWithColor : (currentColor: "blue" | "yellow") => void
|
||||
>currentColor : "blue" | "yellow"
|
||||
|
||||
return draw({ color: currentColor });
|
||||
>draw({ color: currentColor }) : void
|
||||
>draw : (val: Blue | Yellow) => void
|
||||
>{ color: currentColor } : { color: "blue" | "yellow"; }
|
||||
>color : "blue" | "yellow"
|
||||
>currentColor : "blue" | "yellow"
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/12052
|
||||
namespace GH12052 {
|
||||
>GH12052 : typeof GH12052
|
||||
|
||||
interface ILinearAxis { type: "linear"; }
|
||||
>type : "linear"
|
||||
|
||||
interface ICategoricalAxis { type: "categorical"; }
|
||||
>type : "categorical"
|
||||
|
||||
type IAxis = ILinearAxis | ICategoricalAxis;
|
||||
>IAxis : IAxis
|
||||
|
||||
type IAxisType = "linear" | "categorical";
|
||||
>IAxisType : IAxisType
|
||||
|
||||
function getAxisType(): IAxisType {
|
||||
>getAxisType : () => IAxisType
|
||||
|
||||
if (1 == 1) {
|
||||
>1 == 1 : boolean
|
||||
>1 : 1
|
||||
>1 : 1
|
||||
|
||||
return "categorical";
|
||||
>"categorical" : "categorical"
|
||||
|
||||
} else {
|
||||
return "linear";
|
||||
>"linear" : "linear"
|
||||
}
|
||||
}
|
||||
|
||||
const bad: IAxis = { type: getAxisType() };
|
||||
>bad : IAxis
|
||||
>{ type: getAxisType() } : { type: IAxisType; }
|
||||
>type : IAxisType
|
||||
>getAxisType() : IAxisType
|
||||
>getAxisType : () => IAxisType
|
||||
|
||||
const good: IAxis = { type: undefined };
|
||||
>good : IAxis
|
||||
>{ type: undefined } : { type: undefined; }
|
||||
>type : undefined
|
||||
>undefined : undefined
|
||||
|
||||
good.type = getAxisType();
|
||||
>good.type = getAxisType() : IAxisType
|
||||
>good.type : IAxisType
|
||||
>good : IAxis
|
||||
>type : IAxisType
|
||||
>getAxisType() : IAxisType
|
||||
>getAxisType : () => IAxisType
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/18421
|
||||
namespace GH18421 {
|
||||
>GH18421 : typeof GH18421
|
||||
|
||||
interface ThingTypeOne {
|
||||
type: 'one';
|
||||
>type : "one"
|
||||
}
|
||||
|
||||
interface ThingTypeTwo {
|
||||
type: 'two';
|
||||
>type : "two"
|
||||
}
|
||||
|
||||
type ThingType = 'one' | 'two';
|
||||
>ThingType : ThingType
|
||||
|
||||
type Thing = ThingTypeOne | ThingTypeTwo;
|
||||
>Thing : Thing
|
||||
|
||||
function makeNewThing(thingType: ThingType): Thing {
|
||||
>makeNewThing : (thingType: ThingType) => Thing
|
||||
>thingType : ThingType
|
||||
|
||||
return {
|
||||
>{ type: thingType } : { type: ThingType; }
|
||||
|
||||
type: thingType
|
||||
>type : ThingType
|
||||
>thingType : ThingType
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/15907
|
||||
namespace GH15907 {
|
||||
>GH15907 : typeof GH15907
|
||||
|
||||
type Action = { type: 'activate' } | { type: 'disactivate' };
|
||||
>Action : Action
|
||||
>type : "activate"
|
||||
>type : "disactivate"
|
||||
|
||||
function dispatchAction(action: Action): void {
|
||||
>dispatchAction : (action: Action) => void
|
||||
>action : Action
|
||||
|
||||
}
|
||||
|
||||
const active = true;
|
||||
>active : true
|
||||
>true : true
|
||||
|
||||
dispatchAction({ type : (active? 'disactivate' : 'activate') });
|
||||
>dispatchAction({ type : (active? 'disactivate' : 'activate') }) : void
|
||||
>dispatchAction : (action: Action) => void
|
||||
>{ type : (active? 'disactivate' : 'activate') } : { type: "activate" | "disactivate"; }
|
||||
>type : "activate" | "disactivate"
|
||||
>(active? 'disactivate' : 'activate') : "activate" | "disactivate"
|
||||
>active? 'disactivate' : 'activate' : "activate" | "disactivate"
|
||||
>active : true
|
||||
>'disactivate' : "disactivate"
|
||||
>'activate' : "activate"
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/20889
|
||||
namespace GH20889 {
|
||||
>GH20889 : typeof GH20889
|
||||
|
||||
interface A1 {
|
||||
type: "A1";
|
||||
>type : "A1"
|
||||
}
|
||||
interface A2 {
|
||||
type: "A2";
|
||||
>type : "A2"
|
||||
}
|
||||
type AU = A1 | A2;
|
||||
>AU : AU
|
||||
|
||||
function foo(obj1: AU) {
|
||||
>foo : (obj1: AU) => void
|
||||
>obj1 : AU
|
||||
|
||||
const obj2: AU = {
|
||||
>obj2 : AU
|
||||
>{ type: obj1.type } : { type: "A1" | "A2"; }
|
||||
|
||||
type: obj1.type
|
||||
>type : "A1" | "A2"
|
||||
>obj1.type : "A1" | "A2"
|
||||
>obj1 : AU
|
||||
>type : "A1" | "A2"
|
||||
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
// see 'typeRelatedToDiscriminatedType' in checker.ts:
|
||||
|
||||
// IteratorResult
|
||||
namespace Example1 {
|
||||
type S = { done: boolean, value: number };
|
||||
type T =
|
||||
| { done: true, value: number } // T0
|
||||
| { done: false, value: number }; // T1
|
||||
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S is assignable to T0 when S["done"] is true
|
||||
// S is assignable to T1 when S["done"] is false
|
||||
t = s;
|
||||
}
|
||||
|
||||
// Dropping constituents of T
|
||||
namespace Example2 {
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
| { a: 1, b: 2 } // T1
|
||||
| { a: 2, b: 3 | 4 }; // T2
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is assignable to T2 when S["a"] is 2
|
||||
t = s;
|
||||
}
|
||||
|
||||
// Unmatched discriminants
|
||||
namespace Example3 {
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
| { a: 1, b: 2 | 4 } // T1
|
||||
| { a: 2, b: 3 }; // T2
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is *not* assignable to T1 when S["b"] is 4
|
||||
// S is *not* assignable to T2 when S["a"] is 2
|
||||
t = s;
|
||||
}
|
||||
|
||||
// Unmatched non-discriminants
|
||||
namespace Example4 {
|
||||
type S = { a: 0 | 2, b: 4 };
|
||||
type T = { a: 0, b: 1 | 4 } // T0
|
||||
| { a: 1, b: 2 } // T1
|
||||
| { a: 2, b: 3 | 4, c: string }; // T2
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S is assignable to T0 when S["a"] is 0
|
||||
// S is *not* assignable to T2 when S["a"] is 2 as S is missing "c"
|
||||
t = s;
|
||||
}
|
||||
|
||||
// Maximum discriminant combinations
|
||||
namespace Example5 {
|
||||
// NOTE: The maximum number of discriminant type combinations is currently 25.
|
||||
// 3 discriminant properties with 3 types a piece
|
||||
// is 27 possible combinations.
|
||||
type N = 0 | 1 | 2;
|
||||
type S = { a: N, b: N, c: N };
|
||||
type T = { a: 0, b: N, c: N }
|
||||
| { a: 1, b: N, c: N }
|
||||
| { a: 2, b: N, c: N }
|
||||
| { a: N, b: 0, c: N }
|
||||
| { a: N, b: 1, c: N }
|
||||
| { a: N, b: 2, c: N }
|
||||
| { a: N, b: N, c: 0 }
|
||||
| { a: N, b: N, c: 1 }
|
||||
| { a: N, b: N, c: 2 };
|
||||
declare let s: S;
|
||||
declare let t: T;
|
||||
|
||||
// S *should* be assignable but the number of
|
||||
// combinations is too complex.
|
||||
t = s;
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/14865
|
||||
namespace GH14865 {
|
||||
type Style1 = {
|
||||
type: "A";
|
||||
data: string;
|
||||
} | {
|
||||
type: "B";
|
||||
data: string;
|
||||
};
|
||||
|
||||
type Style2 = {
|
||||
type: "A" | "B";
|
||||
data: string;
|
||||
}
|
||||
|
||||
const a: Style2 = { type: "A", data: "whatevs" };
|
||||
let b: Style1;
|
||||
a.type; // "A" | "B"
|
||||
b.type; // "A" | "B"
|
||||
b = a; // should be assignable
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/30170
|
||||
namespace GH30170 {
|
||||
interface Blue {
|
||||
color: 'blue'
|
||||
}
|
||||
interface Yellow {
|
||||
color?: 'yellow',
|
||||
}
|
||||
function draw(val: Blue | Yellow) { }
|
||||
|
||||
function drawWithColor(currentColor: 'blue' | 'yellow' | undefined) {
|
||||
return draw({ color: currentColor });
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/12052
|
||||
namespace GH12052 {
|
||||
interface ILinearAxis { type: "linear"; }
|
||||
|
||||
interface ICategoricalAxis { type: "categorical"; }
|
||||
|
||||
type IAxis = ILinearAxis | ICategoricalAxis;
|
||||
type IAxisType = "linear" | "categorical";
|
||||
|
||||
function getAxisType(): IAxisType {
|
||||
if (1 == 1) {
|
||||
return "categorical";
|
||||
} else {
|
||||
return "linear";
|
||||
}
|
||||
}
|
||||
|
||||
const bad: IAxis = { type: getAxisType() };
|
||||
const good: IAxis = { type: undefined };
|
||||
good.type = getAxisType();
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/18421
|
||||
namespace GH18421 {
|
||||
interface ThingTypeOne {
|
||||
type: 'one';
|
||||
}
|
||||
|
||||
interface ThingTypeTwo {
|
||||
type: 'two';
|
||||
}
|
||||
|
||||
type ThingType = 'one' | 'two';
|
||||
|
||||
type Thing = ThingTypeOne | ThingTypeTwo;
|
||||
|
||||
function makeNewThing(thingType: ThingType): Thing {
|
||||
return {
|
||||
type: thingType
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/15907
|
||||
namespace GH15907 {
|
||||
type Action = { type: 'activate' } | { type: 'disactivate' };
|
||||
|
||||
function dispatchAction(action: Action): void {
|
||||
|
||||
}
|
||||
|
||||
const active = true;
|
||||
|
||||
dispatchAction({ type : (active? 'disactivate' : 'activate') });
|
||||
}
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/20889
|
||||
namespace GH20889 {
|
||||
interface A1 {
|
||||
type: "A1";
|
||||
}
|
||||
interface A2 {
|
||||
type: "A2";
|
||||
}
|
||||
type AU = A1 | A2;
|
||||
|
||||
function foo(obj1: AU) {
|
||||
const obj2: AU = {
|
||||
type: obj1.type
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue