mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #28942 from Microsoft/missing3.2Prs
Port missing 3.2 PRs
This commit is contained in:
+47
-32
@@ -9786,14 +9786,11 @@ namespace ts {
|
||||
if (checkType === wildcardType || extendsType === wildcardType) {
|
||||
return wildcardType;
|
||||
}
|
||||
// If this is a distributive conditional type and the check type is generic we need to defer
|
||||
// resolution of the conditional type such that a later instantiation will properly distribute
|
||||
// over union types.
|
||||
const isDeferred = root.isDistributive && maybeTypeOfKind(checkType, TypeFlags.Instantiable);
|
||||
const checkTypeInstantiable = maybeTypeOfKind(checkType, TypeFlags.Instantiable);
|
||||
let combinedMapper: TypeMapper | undefined;
|
||||
if (root.inferTypeParameters) {
|
||||
const context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, InferenceFlags.None);
|
||||
if (!isDeferred) {
|
||||
if (!checkTypeInstantiable) {
|
||||
// We don't want inferences from constraints as they may cause us to eagerly resolve the
|
||||
// conditional type instead of deferring resolution. Also, we always want strict function
|
||||
// types rules (i.e. proper contravariance) for inferences.
|
||||
@@ -9801,16 +9798,17 @@ namespace ts {
|
||||
}
|
||||
combinedMapper = combineTypeMappers(mapper, context);
|
||||
}
|
||||
if (!isDeferred) {
|
||||
if (extendsType.flags & TypeFlags.AnyOrUnknown) {
|
||||
// Instantiate the extends type including inferences for 'infer T' type parameters
|
||||
const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType;
|
||||
// We attempt to resolve the conditional type only when the check and extends types are non-generic
|
||||
if (!checkTypeInstantiable && !maybeTypeOfKind(inferredExtendsType, TypeFlags.Instantiable)) {
|
||||
if (inferredExtendsType.flags & TypeFlags.AnyOrUnknown) {
|
||||
return instantiateType(root.trueType, mapper);
|
||||
}
|
||||
// Return union of trueType and falseType for 'any' since it matches anything
|
||||
if (checkType.flags & TypeFlags.Any) {
|
||||
return getUnionType([instantiateType(root.trueType, combinedMapper || mapper), instantiateType(root.falseType, mapper)]);
|
||||
}
|
||||
// Instantiate the extends type including inferences for 'infer T' type parameters
|
||||
const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType;
|
||||
// Return falseType for a definitely false extends check. We check an instantations of the two
|
||||
// types with type parameters mapped to the wildcard type, the most permissive instantiations
|
||||
// possible (the wildcard type is assignable to and from all types). If those are not related,
|
||||
@@ -11838,7 +11836,7 @@ namespace ts {
|
||||
if (!noImplicitAny && getObjectFlags(target) & ObjectFlags.JSLiteral) {
|
||||
return false; // Disable excess property checks on JS literals to simulate having an implicit "index signature" - but only outside of noImplicitAny
|
||||
}
|
||||
if (maybeTypeOfKind(target, TypeFlags.Object) && !(getObjectFlags(target) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) {
|
||||
if (isExcessPropertyCheckTarget(target)) {
|
||||
const isComparingJsxAttributes = !!(getObjectFlags(source) & ObjectFlags.JsxAttributes);
|
||||
if ((relation === assignableRelation || relation === definitelyAssignableRelation || relation === comparableRelation) &&
|
||||
(isTypeSubsetOf(globalObjectType, target) || (!isComparingJsxAttributes && isEmptyObjectType(target)))) {
|
||||
@@ -11851,6 +11849,9 @@ namespace ts {
|
||||
for (const prop of getPropertiesOfObjectType(source)) {
|
||||
if (shouldCheckAsExcessProperty(prop, source.symbol) && !isKnownProperty(target, prop.escapedName, isComparingJsxAttributes)) {
|
||||
if (reportErrors) {
|
||||
// Report error in terms of object types in the target as those are the only ones
|
||||
// we check in isKnownProperty.
|
||||
const errorTarget = filterType(target, isExcessPropertyCheckTarget);
|
||||
// We know *exactly* where things went wrong when comparing the types.
|
||||
// Use this property as the error node as this will be more helpful in
|
||||
// reasoning about what went wrong.
|
||||
@@ -11859,7 +11860,7 @@ namespace ts {
|
||||
// JsxAttributes has an object-literal flag and undergo same type-assignablity check as normal object-literal.
|
||||
// However, using an object-literal error message will be very confusing to the users so we give different a message.
|
||||
// TODO: Spelling suggestions for excess jsx attributes (needs new diagnostic messages)
|
||||
reportError(Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(prop), typeToString(target));
|
||||
reportError(Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(prop), typeToString(errorTarget));
|
||||
}
|
||||
else {
|
||||
// use the property's value declaration if the property is assigned inside the literal itself
|
||||
@@ -11873,17 +11874,17 @@ namespace ts {
|
||||
|
||||
const name = propDeclaration.name!;
|
||||
if (isIdentifier(name)) {
|
||||
suggestion = getSuggestionForNonexistentProperty(name, target);
|
||||
suggestion = getSuggestionForNonexistentProperty(name, errorTarget);
|
||||
}
|
||||
}
|
||||
|
||||
if (suggestion !== undefined) {
|
||||
reportError(Diagnostics.Object_literal_may_only_specify_known_properties_but_0_does_not_exist_in_type_1_Did_you_mean_to_write_2,
|
||||
symbolToString(prop), typeToString(target), suggestion);
|
||||
symbolToString(prop), typeToString(errorTarget), suggestion);
|
||||
}
|
||||
else {
|
||||
reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1,
|
||||
symbolToString(prop), typeToString(target));
|
||||
symbolToString(prop), typeToString(errorTarget));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14616,15 +14617,15 @@ namespace ts {
|
||||
getAccessedPropertyName(source as PropertyAccessExpression | ElementAccessExpression) === getAccessedPropertyName(target) &&
|
||||
isMatchingReference((source as PropertyAccessExpression | ElementAccessExpression).expression, target.expression);
|
||||
case SyntaxKind.BindingElement:
|
||||
if (target.kind !== SyntaxKind.PropertyAccessExpression) return false;
|
||||
const t = target as PropertyAccessExpression;
|
||||
if (t.name.escapedText !== getBindingElementNameText(source as BindingElement)) return false;
|
||||
if (source.parent.parent.kind === SyntaxKind.BindingElement && isMatchingReference(source.parent.parent, t.expression)) {
|
||||
return true;
|
||||
}
|
||||
if (source.parent.parent.kind === SyntaxKind.VariableDeclaration) {
|
||||
const maybeId = (source.parent.parent as VariableDeclaration).initializer;
|
||||
return !!maybeId && isMatchingReference(maybeId, t.expression);
|
||||
if (target.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>target).name.escapedText === getBindingElementNameText(<BindingElement>source)) {
|
||||
const ancestor = source.parent.parent;
|
||||
if (ancestor.kind === SyntaxKind.BindingElement) {
|
||||
return isMatchingReference(ancestor, (<PropertyAccessExpression>target).expression);
|
||||
}
|
||||
if (ancestor.kind === SyntaxKind.VariableDeclaration) {
|
||||
const initializer = (<VariableDeclaration>ancestor).initializer;
|
||||
return !!initializer && isMatchingReference(initializer, (<PropertyAccessExpression>target).expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -14636,14 +14637,25 @@ namespace ts {
|
||||
undefined;
|
||||
}
|
||||
|
||||
function getReferenceParent(source: Node) {
|
||||
if (source.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
return (<PropertyAccessExpression>source).expression;
|
||||
}
|
||||
if (source.kind === SyntaxKind.BindingElement) {
|
||||
const ancestor = source.parent.parent;
|
||||
return ancestor.kind === SyntaxKind.VariableDeclaration ? (<VariableDeclaration>ancestor).initializer : ancestor;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function containsMatchingReference(source: Node, target: Node) {
|
||||
while (source.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
source = (<PropertyAccessExpression>source).expression;
|
||||
if (isMatchingReference(source, target)) {
|
||||
let parent = getReferenceParent(source);
|
||||
while (parent) {
|
||||
if (isMatchingReference(parent, target)) {
|
||||
return true;
|
||||
}
|
||||
parent = getReferenceParent(parent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return true if target is a property access xxx.yyy, source is a property access xxx.zzz, the declared
|
||||
@@ -18585,20 +18597,23 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (targetType.flags & TypeFlags.UnionOrIntersection) {
|
||||
else if (targetType.flags & TypeFlags.UnionOrIntersection && isExcessPropertyCheckTarget(targetType)) {
|
||||
for (const t of (targetType as UnionOrIntersectionType).types) {
|
||||
if (isKnownProperty(t, name, isComparingJsxAttributes)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (targetType.flags & TypeFlags.Conditional) {
|
||||
return isKnownProperty((targetType as ConditionalType).root.trueType, name, isComparingJsxAttributes) ||
|
||||
isKnownProperty((targetType as ConditionalType).root.falseType, name, isComparingJsxAttributes);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isExcessPropertyCheckTarget(type: Type): boolean {
|
||||
return !!(type.flags & TypeFlags.Object && !(getObjectFlags(type) & ObjectFlags.ObjectLiteralPatternWithComputedProperties) ||
|
||||
type.flags & TypeFlags.NonPrimitive ||
|
||||
type.flags & TypeFlags.Union && some((<UnionType>type).types, isExcessPropertyCheckTarget) ||
|
||||
type.flags & TypeFlags.Intersection && every((<IntersectionType>type).types, isExcessPropertyCheckTarget));
|
||||
}
|
||||
|
||||
function checkJsxExpression(node: JsxExpression, checkMode?: CheckMode) {
|
||||
if (node.expression) {
|
||||
const type = checkExpression(node.expression, checkMode);
|
||||
|
||||
@@ -203,4 +203,47 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
|
||||
|
||||
type C2<T, V, E> =
|
||||
T extends object ? { [Q in keyof T]: C2<T[Q], V, E>; } : T;
|
||||
|
||||
// Repro from #28654
|
||||
|
||||
type MaybeTrue<T extends { b: boolean }> = true extends T["b"] ? "yes" : "no";
|
||||
|
||||
type T0 = MaybeTrue<{ b: never }> // "no"
|
||||
type T1 = MaybeTrue<{ b: false }>; // "no"
|
||||
type T2 = MaybeTrue<{ b: true }>; // "yes"
|
||||
type T3 = MaybeTrue<{ b: boolean }>; // "yes"
|
||||
|
||||
// Repro from #28824
|
||||
|
||||
type Union = 'a' | 'b';
|
||||
type Product<A extends Union, B> = { f1: A, f2: B};
|
||||
type ProductUnion = Product<'a', 0> | Product<'b', 1>;
|
||||
|
||||
// {a: "b"; b: "a"}
|
||||
type UnionComplement = {
|
||||
[K in Union]: Exclude<Union, K>
|
||||
};
|
||||
type UCA = UnionComplement['a'];
|
||||
type UCB = UnionComplement['b'];
|
||||
|
||||
// {a: "a"; b: "b"}
|
||||
type UnionComplementComplement = {
|
||||
[K in Union]: Exclude<Union, Exclude<Union, K>>
|
||||
};
|
||||
type UCCA = UnionComplementComplement['a'];
|
||||
type UCCB = UnionComplementComplement['b'];
|
||||
|
||||
// {a: Product<'b', 1>; b: Product<'a', 0>}
|
||||
type ProductComplement = {
|
||||
[K in Union]: Exclude<ProductUnion, { f1: K }>
|
||||
};
|
||||
type PCA = ProductComplement['a'];
|
||||
type PCB = ProductComplement['b'];
|
||||
|
||||
// {a: Product<'a', 0>; b: Product<'b', 1>}
|
||||
type ProductComplementComplement = {
|
||||
[K in Union]: Exclude<ProductUnion, Exclude<ProductUnion, { f1: K }>>
|
||||
};
|
||||
type PCCA = ProductComplementComplement['a'];
|
||||
type PCCB = ProductComplementComplement['b'];
|
||||
|
||||
@@ -145,6 +145,49 @@ type B2<T, V> =
|
||||
|
||||
type C2<T, V, E> =
|
||||
T extends object ? { [Q in keyof T]: C2<T[Q], V, E>; } : T;
|
||||
|
||||
// Repro from #28654
|
||||
|
||||
type MaybeTrue<T extends { b: boolean }> = true extends T["b"] ? "yes" : "no";
|
||||
|
||||
type T0 = MaybeTrue<{ b: never }> // "no"
|
||||
type T1 = MaybeTrue<{ b: false }>; // "no"
|
||||
type T2 = MaybeTrue<{ b: true }>; // "yes"
|
||||
type T3 = MaybeTrue<{ b: boolean }>; // "yes"
|
||||
|
||||
// Repro from #28824
|
||||
|
||||
type Union = 'a' | 'b';
|
||||
type Product<A extends Union, B> = { f1: A, f2: B};
|
||||
type ProductUnion = Product<'a', 0> | Product<'b', 1>;
|
||||
|
||||
// {a: "b"; b: "a"}
|
||||
type UnionComplement = {
|
||||
[K in Union]: Exclude<Union, K>
|
||||
};
|
||||
type UCA = UnionComplement['a'];
|
||||
type UCB = UnionComplement['b'];
|
||||
|
||||
// {a: "a"; b: "b"}
|
||||
type UnionComplementComplement = {
|
||||
[K in Union]: Exclude<Union, Exclude<Union, K>>
|
||||
};
|
||||
type UCCA = UnionComplementComplement['a'];
|
||||
type UCCB = UnionComplementComplement['b'];
|
||||
|
||||
// {a: Product<'b', 1>; b: Product<'a', 0>}
|
||||
type ProductComplement = {
|
||||
[K in Union]: Exclude<ProductUnion, { f1: K }>
|
||||
};
|
||||
type PCA = ProductComplement['a'];
|
||||
type PCB = ProductComplement['b'];
|
||||
|
||||
// {a: Product<'a', 0>; b: Product<'b', 1>}
|
||||
type ProductComplementComplement = {
|
||||
[K in Union]: Exclude<ProductUnion, Exclude<ProductUnion, { f1: K }>>
|
||||
};
|
||||
type PCCA = ProductComplementComplement['a'];
|
||||
type PCCB = ProductComplementComplement['b'];
|
||||
|
||||
|
||||
//// [conditionalTypes2.js]
|
||||
@@ -304,3 +347,48 @@ declare type B2<T, V> = T extends object ? T extends any[] ? T : {
|
||||
declare type C2<T, V, E> = T extends object ? {
|
||||
[Q in keyof T]: C2<T[Q], V, E>;
|
||||
} : T;
|
||||
declare type MaybeTrue<T extends {
|
||||
b: boolean;
|
||||
}> = true extends T["b"] ? "yes" : "no";
|
||||
declare type T0 = MaybeTrue<{
|
||||
b: never;
|
||||
}>;
|
||||
declare type T1 = MaybeTrue<{
|
||||
b: false;
|
||||
}>;
|
||||
declare type T2 = MaybeTrue<{
|
||||
b: true;
|
||||
}>;
|
||||
declare type T3 = MaybeTrue<{
|
||||
b: boolean;
|
||||
}>;
|
||||
declare type Union = 'a' | 'b';
|
||||
declare type Product<A extends Union, B> = {
|
||||
f1: A;
|
||||
f2: B;
|
||||
};
|
||||
declare type ProductUnion = Product<'a', 0> | Product<'b', 1>;
|
||||
declare type UnionComplement = {
|
||||
[K in Union]: Exclude<Union, K>;
|
||||
};
|
||||
declare type UCA = UnionComplement['a'];
|
||||
declare type UCB = UnionComplement['b'];
|
||||
declare type UnionComplementComplement = {
|
||||
[K in Union]: Exclude<Union, Exclude<Union, K>>;
|
||||
};
|
||||
declare type UCCA = UnionComplementComplement['a'];
|
||||
declare type UCCB = UnionComplementComplement['b'];
|
||||
declare type ProductComplement = {
|
||||
[K in Union]: Exclude<ProductUnion, {
|
||||
f1: K;
|
||||
}>;
|
||||
};
|
||||
declare type PCA = ProductComplement['a'];
|
||||
declare type PCB = ProductComplement['b'];
|
||||
declare type ProductComplementComplement = {
|
||||
[K in Union]: Exclude<ProductUnion, Exclude<ProductUnion, {
|
||||
f1: K;
|
||||
}>>;
|
||||
};
|
||||
declare type PCCA = ProductComplementComplement['a'];
|
||||
declare type PCCB = ProductComplementComplement['b'];
|
||||
|
||||
@@ -551,3 +551,137 @@ type C2<T, V, E> =
|
||||
>E : Symbol(E, Decl(conditionalTypes2.ts, 144, 13))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 144, 8))
|
||||
|
||||
// Repro from #28654
|
||||
|
||||
type MaybeTrue<T extends { b: boolean }> = true extends T["b"] ? "yes" : "no";
|
||||
>MaybeTrue : Symbol(MaybeTrue, Decl(conditionalTypes2.ts, 145, 63))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 149, 15))
|
||||
>b : Symbol(b, Decl(conditionalTypes2.ts, 149, 26))
|
||||
>T : Symbol(T, Decl(conditionalTypes2.ts, 149, 15))
|
||||
|
||||
type T0 = MaybeTrue<{ b: never }> // "no"
|
||||
>T0 : Symbol(T0, Decl(conditionalTypes2.ts, 149, 78))
|
||||
>MaybeTrue : Symbol(MaybeTrue, Decl(conditionalTypes2.ts, 145, 63))
|
||||
>b : Symbol(b, Decl(conditionalTypes2.ts, 151, 21))
|
||||
|
||||
type T1 = MaybeTrue<{ b: false }>; // "no"
|
||||
>T1 : Symbol(T1, Decl(conditionalTypes2.ts, 151, 33))
|
||||
>MaybeTrue : Symbol(MaybeTrue, Decl(conditionalTypes2.ts, 145, 63))
|
||||
>b : Symbol(b, Decl(conditionalTypes2.ts, 152, 21))
|
||||
|
||||
type T2 = MaybeTrue<{ b: true }>; // "yes"
|
||||
>T2 : Symbol(T2, Decl(conditionalTypes2.ts, 152, 34))
|
||||
>MaybeTrue : Symbol(MaybeTrue, Decl(conditionalTypes2.ts, 145, 63))
|
||||
>b : Symbol(b, Decl(conditionalTypes2.ts, 153, 21))
|
||||
|
||||
type T3 = MaybeTrue<{ b: boolean }>; // "yes"
|
||||
>T3 : Symbol(T3, Decl(conditionalTypes2.ts, 153, 33))
|
||||
>MaybeTrue : Symbol(MaybeTrue, Decl(conditionalTypes2.ts, 145, 63))
|
||||
>b : Symbol(b, Decl(conditionalTypes2.ts, 154, 21))
|
||||
|
||||
// Repro from #28824
|
||||
|
||||
type Union = 'a' | 'b';
|
||||
>Union : Symbol(Union, Decl(conditionalTypes2.ts, 154, 36))
|
||||
|
||||
type Product<A extends Union, B> = { f1: A, f2: B};
|
||||
>Product : Symbol(Product, Decl(conditionalTypes2.ts, 158, 23))
|
||||
>A : Symbol(A, Decl(conditionalTypes2.ts, 159, 13))
|
||||
>Union : Symbol(Union, Decl(conditionalTypes2.ts, 154, 36))
|
||||
>B : Symbol(B, Decl(conditionalTypes2.ts, 159, 29))
|
||||
>f1 : Symbol(f1, Decl(conditionalTypes2.ts, 159, 36))
|
||||
>A : Symbol(A, Decl(conditionalTypes2.ts, 159, 13))
|
||||
>f2 : Symbol(f2, Decl(conditionalTypes2.ts, 159, 43))
|
||||
>B : Symbol(B, Decl(conditionalTypes2.ts, 159, 29))
|
||||
|
||||
type ProductUnion = Product<'a', 0> | Product<'b', 1>;
|
||||
>ProductUnion : Symbol(ProductUnion, Decl(conditionalTypes2.ts, 159, 51))
|
||||
>Product : Symbol(Product, Decl(conditionalTypes2.ts, 158, 23))
|
||||
>Product : Symbol(Product, Decl(conditionalTypes2.ts, 158, 23))
|
||||
|
||||
// {a: "b"; b: "a"}
|
||||
type UnionComplement = {
|
||||
>UnionComplement : Symbol(UnionComplement, Decl(conditionalTypes2.ts, 160, 54))
|
||||
|
||||
[K in Union]: Exclude<Union, K>
|
||||
>K : Symbol(K, Decl(conditionalTypes2.ts, 164, 3))
|
||||
>Union : Symbol(Union, Decl(conditionalTypes2.ts, 154, 36))
|
||||
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
|
||||
>Union : Symbol(Union, Decl(conditionalTypes2.ts, 154, 36))
|
||||
>K : Symbol(K, Decl(conditionalTypes2.ts, 164, 3))
|
||||
|
||||
};
|
||||
type UCA = UnionComplement['a'];
|
||||
>UCA : Symbol(UCA, Decl(conditionalTypes2.ts, 165, 2))
|
||||
>UnionComplement : Symbol(UnionComplement, Decl(conditionalTypes2.ts, 160, 54))
|
||||
|
||||
type UCB = UnionComplement['b'];
|
||||
>UCB : Symbol(UCB, Decl(conditionalTypes2.ts, 166, 32))
|
||||
>UnionComplement : Symbol(UnionComplement, Decl(conditionalTypes2.ts, 160, 54))
|
||||
|
||||
// {a: "a"; b: "b"}
|
||||
type UnionComplementComplement = {
|
||||
>UnionComplementComplement : Symbol(UnionComplementComplement, Decl(conditionalTypes2.ts, 167, 32))
|
||||
|
||||
[K in Union]: Exclude<Union, Exclude<Union, K>>
|
||||
>K : Symbol(K, Decl(conditionalTypes2.ts, 171, 3))
|
||||
>Union : Symbol(Union, Decl(conditionalTypes2.ts, 154, 36))
|
||||
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
|
||||
>Union : Symbol(Union, Decl(conditionalTypes2.ts, 154, 36))
|
||||
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
|
||||
>Union : Symbol(Union, Decl(conditionalTypes2.ts, 154, 36))
|
||||
>K : Symbol(K, Decl(conditionalTypes2.ts, 171, 3))
|
||||
|
||||
};
|
||||
type UCCA = UnionComplementComplement['a'];
|
||||
>UCCA : Symbol(UCCA, Decl(conditionalTypes2.ts, 172, 2))
|
||||
>UnionComplementComplement : Symbol(UnionComplementComplement, Decl(conditionalTypes2.ts, 167, 32))
|
||||
|
||||
type UCCB = UnionComplementComplement['b'];
|
||||
>UCCB : Symbol(UCCB, Decl(conditionalTypes2.ts, 173, 43))
|
||||
>UnionComplementComplement : Symbol(UnionComplementComplement, Decl(conditionalTypes2.ts, 167, 32))
|
||||
|
||||
// {a: Product<'b', 1>; b: Product<'a', 0>}
|
||||
type ProductComplement = {
|
||||
>ProductComplement : Symbol(ProductComplement, Decl(conditionalTypes2.ts, 174, 43))
|
||||
|
||||
[K in Union]: Exclude<ProductUnion, { f1: K }>
|
||||
>K : Symbol(K, Decl(conditionalTypes2.ts, 178, 3))
|
||||
>Union : Symbol(Union, Decl(conditionalTypes2.ts, 154, 36))
|
||||
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
|
||||
>ProductUnion : Symbol(ProductUnion, Decl(conditionalTypes2.ts, 159, 51))
|
||||
>f1 : Symbol(f1, Decl(conditionalTypes2.ts, 178, 39))
|
||||
>K : Symbol(K, Decl(conditionalTypes2.ts, 178, 3))
|
||||
|
||||
};
|
||||
type PCA = ProductComplement['a'];
|
||||
>PCA : Symbol(PCA, Decl(conditionalTypes2.ts, 179, 2))
|
||||
>ProductComplement : Symbol(ProductComplement, Decl(conditionalTypes2.ts, 174, 43))
|
||||
|
||||
type PCB = ProductComplement['b'];
|
||||
>PCB : Symbol(PCB, Decl(conditionalTypes2.ts, 180, 34))
|
||||
>ProductComplement : Symbol(ProductComplement, Decl(conditionalTypes2.ts, 174, 43))
|
||||
|
||||
// {a: Product<'a', 0>; b: Product<'b', 1>}
|
||||
type ProductComplementComplement = {
|
||||
>ProductComplementComplement : Symbol(ProductComplementComplement, Decl(conditionalTypes2.ts, 181, 34))
|
||||
|
||||
[K in Union]: Exclude<ProductUnion, Exclude<ProductUnion, { f1: K }>>
|
||||
>K : Symbol(K, Decl(conditionalTypes2.ts, 185, 3))
|
||||
>Union : Symbol(Union, Decl(conditionalTypes2.ts, 154, 36))
|
||||
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
|
||||
>ProductUnion : Symbol(ProductUnion, Decl(conditionalTypes2.ts, 159, 51))
|
||||
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
|
||||
>ProductUnion : Symbol(ProductUnion, Decl(conditionalTypes2.ts, 159, 51))
|
||||
>f1 : Symbol(f1, Decl(conditionalTypes2.ts, 185, 61))
|
||||
>K : Symbol(K, Decl(conditionalTypes2.ts, 185, 3))
|
||||
|
||||
};
|
||||
type PCCA = ProductComplementComplement['a'];
|
||||
>PCCA : Symbol(PCCA, Decl(conditionalTypes2.ts, 186, 2))
|
||||
>ProductComplementComplement : Symbol(ProductComplementComplement, Decl(conditionalTypes2.ts, 181, 34))
|
||||
|
||||
type PCCB = ProductComplementComplement['b'];
|
||||
>PCCB : Symbol(PCCB, Decl(conditionalTypes2.ts, 187, 45))
|
||||
>ProductComplementComplement : Symbol(ProductComplementComplement, Decl(conditionalTypes2.ts, 181, 34))
|
||||
|
||||
|
||||
@@ -341,3 +341,93 @@ type C2<T, V, E> =
|
||||
|
||||
T extends object ? { [Q in keyof T]: C2<T[Q], V, E>; } : T;
|
||||
|
||||
// Repro from #28654
|
||||
|
||||
type MaybeTrue<T extends { b: boolean }> = true extends T["b"] ? "yes" : "no";
|
||||
>MaybeTrue : MaybeTrue<T>
|
||||
>b : boolean
|
||||
>true : true
|
||||
|
||||
type T0 = MaybeTrue<{ b: never }> // "no"
|
||||
>T0 : "no"
|
||||
>b : never
|
||||
|
||||
type T1 = MaybeTrue<{ b: false }>; // "no"
|
||||
>T1 : "no"
|
||||
>b : false
|
||||
>false : false
|
||||
|
||||
type T2 = MaybeTrue<{ b: true }>; // "yes"
|
||||
>T2 : "yes"
|
||||
>b : true
|
||||
>true : true
|
||||
|
||||
type T3 = MaybeTrue<{ b: boolean }>; // "yes"
|
||||
>T3 : "yes"
|
||||
>b : boolean
|
||||
|
||||
// Repro from #28824
|
||||
|
||||
type Union = 'a' | 'b';
|
||||
>Union : Union
|
||||
|
||||
type Product<A extends Union, B> = { f1: A, f2: B};
|
||||
>Product : Product<A, B>
|
||||
>f1 : A
|
||||
>f2 : B
|
||||
|
||||
type ProductUnion = Product<'a', 0> | Product<'b', 1>;
|
||||
>ProductUnion : ProductUnion
|
||||
|
||||
// {a: "b"; b: "a"}
|
||||
type UnionComplement = {
|
||||
>UnionComplement : UnionComplement
|
||||
|
||||
[K in Union]: Exclude<Union, K>
|
||||
};
|
||||
type UCA = UnionComplement['a'];
|
||||
>UCA : "b"
|
||||
|
||||
type UCB = UnionComplement['b'];
|
||||
>UCB : "a"
|
||||
|
||||
// {a: "a"; b: "b"}
|
||||
type UnionComplementComplement = {
|
||||
>UnionComplementComplement : UnionComplementComplement
|
||||
|
||||
[K in Union]: Exclude<Union, Exclude<Union, K>>
|
||||
};
|
||||
type UCCA = UnionComplementComplement['a'];
|
||||
>UCCA : "a"
|
||||
|
||||
type UCCB = UnionComplementComplement['b'];
|
||||
>UCCB : "b"
|
||||
|
||||
// {a: Product<'b', 1>; b: Product<'a', 0>}
|
||||
type ProductComplement = {
|
||||
>ProductComplement : ProductComplement
|
||||
|
||||
[K in Union]: Exclude<ProductUnion, { f1: K }>
|
||||
>f1 : K
|
||||
|
||||
};
|
||||
type PCA = ProductComplement['a'];
|
||||
>PCA : Product<"b", 1>
|
||||
|
||||
type PCB = ProductComplement['b'];
|
||||
>PCB : Product<"a", 0>
|
||||
|
||||
// {a: Product<'a', 0>; b: Product<'b', 1>}
|
||||
type ProductComplementComplement = {
|
||||
>ProductComplementComplement : ProductComplementComplement
|
||||
|
||||
[K in Union]: Exclude<ProductUnion, Exclude<ProductUnion, { f1: K }>>
|
||||
>f1 : K
|
||||
|
||||
};
|
||||
type PCCA = ProductComplementComplement['a'];
|
||||
>PCCA : Product<"a", 0>
|
||||
|
||||
type PCCB = ProductComplementComplement['b'];
|
||||
>PCCB : Product<"b", 1>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
tests/cases/conformance/types/conditional/conditionalTypesExcessProperties.ts(8,5): error TS2322: Type '{ test: string; arg: A; }' is not assignable to type 'Something<A>'.
|
||||
Type '{ test: string; arg: A; }' is not assignable to type 'A extends object ? { arg: A; } : { arg?: undefined; }'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypesExcessProperties.ts(9,33): error TS2322: Type '{ test: string; arg: A; arr: A; }' is not assignable to type 'Something<A>'.
|
||||
Object literal may only specify known properties, and 'arr' does not exist in type 'Something<A>'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypesExcessProperties.ts(9,5): error TS2322: Type '{ test: string; arg: A; arr: A; }' is not assignable to type 'Something<A>'.
|
||||
Type '{ test: string; arg: A; arr: A; }' is not assignable to type 'A extends object ? { arg: A; } : { arg?: undefined; }'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/conditional/conditionalTypesExcessProperties.ts (2 errors) ====
|
||||
@@ -17,8 +17,8 @@ tests/cases/conformance/types/conditional/conditionalTypesExcessProperties.ts(9,
|
||||
!!! error TS2322: Type '{ test: string; arg: A; }' is not assignable to type 'Something<A>'.
|
||||
!!! error TS2322: Type '{ test: string; arg: A; }' is not assignable to type 'A extends object ? { arg: A; } : { arg?: undefined; }'.
|
||||
sa = { test: 'bye', arg: a, arr: a } // excess
|
||||
~~~~~~
|
||||
~~
|
||||
!!! error TS2322: Type '{ test: string; arg: A; arr: A; }' is not assignable to type 'Something<A>'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'arr' does not exist in type 'Something<A>'.
|
||||
!!! error TS2322: Type '{ test: string; arg: A; arr: A; }' is not assignable to type 'A extends object ? { arg: A; } : { arg?: undefined; }'.
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
//// [controlFlowDestructuringLoop.ts]
|
||||
// Repro from #28758
|
||||
|
||||
interface NumVal { val: number; }
|
||||
interface StrVal { val: string; }
|
||||
type Val = NumVal | StrVal;
|
||||
|
||||
function isNumVal(x: Val): x is NumVal {
|
||||
return typeof x.val === 'number';
|
||||
}
|
||||
|
||||
function foo(things: Val[]): void {
|
||||
for (const thing of things) {
|
||||
if (isNumVal(thing)) {
|
||||
const { val } = thing;
|
||||
val.toFixed(2);
|
||||
}
|
||||
else {
|
||||
const { val } = thing;
|
||||
val.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// [controlFlowDestructuringLoop.js]
|
||||
"use strict";
|
||||
// Repro from #28758
|
||||
function isNumVal(x) {
|
||||
return typeof x.val === 'number';
|
||||
}
|
||||
function foo(things) {
|
||||
for (var _i = 0, things_1 = things; _i < things_1.length; _i++) {
|
||||
var thing = things_1[_i];
|
||||
if (isNumVal(thing)) {
|
||||
var val = thing.val;
|
||||
val.toFixed(2);
|
||||
}
|
||||
else {
|
||||
var val = thing.val;
|
||||
val.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
=== tests/cases/compiler/controlFlowDestructuringLoop.ts ===
|
||||
// Repro from #28758
|
||||
|
||||
interface NumVal { val: number; }
|
||||
>NumVal : Symbol(NumVal, Decl(controlFlowDestructuringLoop.ts, 0, 0))
|
||||
>val : Symbol(NumVal.val, Decl(controlFlowDestructuringLoop.ts, 2, 18))
|
||||
|
||||
interface StrVal { val: string; }
|
||||
>StrVal : Symbol(StrVal, Decl(controlFlowDestructuringLoop.ts, 2, 33))
|
||||
>val : Symbol(StrVal.val, Decl(controlFlowDestructuringLoop.ts, 3, 18))
|
||||
|
||||
type Val = NumVal | StrVal;
|
||||
>Val : Symbol(Val, Decl(controlFlowDestructuringLoop.ts, 3, 33))
|
||||
>NumVal : Symbol(NumVal, Decl(controlFlowDestructuringLoop.ts, 0, 0))
|
||||
>StrVal : Symbol(StrVal, Decl(controlFlowDestructuringLoop.ts, 2, 33))
|
||||
|
||||
function isNumVal(x: Val): x is NumVal {
|
||||
>isNumVal : Symbol(isNumVal, Decl(controlFlowDestructuringLoop.ts, 4, 27))
|
||||
>x : Symbol(x, Decl(controlFlowDestructuringLoop.ts, 6, 18))
|
||||
>Val : Symbol(Val, Decl(controlFlowDestructuringLoop.ts, 3, 33))
|
||||
>x : Symbol(x, Decl(controlFlowDestructuringLoop.ts, 6, 18))
|
||||
>NumVal : Symbol(NumVal, Decl(controlFlowDestructuringLoop.ts, 0, 0))
|
||||
|
||||
return typeof x.val === 'number';
|
||||
>x.val : Symbol(val, Decl(controlFlowDestructuringLoop.ts, 2, 18), Decl(controlFlowDestructuringLoop.ts, 3, 18))
|
||||
>x : Symbol(x, Decl(controlFlowDestructuringLoop.ts, 6, 18))
|
||||
>val : Symbol(val, Decl(controlFlowDestructuringLoop.ts, 2, 18), Decl(controlFlowDestructuringLoop.ts, 3, 18))
|
||||
}
|
||||
|
||||
function foo(things: Val[]): void {
|
||||
>foo : Symbol(foo, Decl(controlFlowDestructuringLoop.ts, 8, 1))
|
||||
>things : Symbol(things, Decl(controlFlowDestructuringLoop.ts, 10, 13))
|
||||
>Val : Symbol(Val, Decl(controlFlowDestructuringLoop.ts, 3, 33))
|
||||
|
||||
for (const thing of things) {
|
||||
>thing : Symbol(thing, Decl(controlFlowDestructuringLoop.ts, 11, 14))
|
||||
>things : Symbol(things, Decl(controlFlowDestructuringLoop.ts, 10, 13))
|
||||
|
||||
if (isNumVal(thing)) {
|
||||
>isNumVal : Symbol(isNumVal, Decl(controlFlowDestructuringLoop.ts, 4, 27))
|
||||
>thing : Symbol(thing, Decl(controlFlowDestructuringLoop.ts, 11, 14))
|
||||
|
||||
const { val } = thing;
|
||||
>val : Symbol(val, Decl(controlFlowDestructuringLoop.ts, 13, 19))
|
||||
>thing : Symbol(thing, Decl(controlFlowDestructuringLoop.ts, 11, 14))
|
||||
|
||||
val.toFixed(2);
|
||||
>val.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
|
||||
>val : Symbol(val, Decl(controlFlowDestructuringLoop.ts, 13, 19))
|
||||
>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --))
|
||||
}
|
||||
else {
|
||||
const { val } = thing;
|
||||
>val : Symbol(val, Decl(controlFlowDestructuringLoop.ts, 17, 19))
|
||||
>thing : Symbol(thing, Decl(controlFlowDestructuringLoop.ts, 11, 14))
|
||||
|
||||
val.length;
|
||||
>val.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
|
||||
>val : Symbol(val, Decl(controlFlowDestructuringLoop.ts, 17, 19))
|
||||
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
=== tests/cases/compiler/controlFlowDestructuringLoop.ts ===
|
||||
// Repro from #28758
|
||||
|
||||
interface NumVal { val: number; }
|
||||
>val : number
|
||||
|
||||
interface StrVal { val: string; }
|
||||
>val : string
|
||||
|
||||
type Val = NumVal | StrVal;
|
||||
>Val : Val
|
||||
|
||||
function isNumVal(x: Val): x is NumVal {
|
||||
>isNumVal : (x: Val) => x is NumVal
|
||||
>x : Val
|
||||
|
||||
return typeof x.val === 'number';
|
||||
>typeof x.val === 'number' : boolean
|
||||
>typeof x.val : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>x.val : string | number
|
||||
>x : Val
|
||||
>val : string | number
|
||||
>'number' : "number"
|
||||
}
|
||||
|
||||
function foo(things: Val[]): void {
|
||||
>foo : (things: Val[]) => void
|
||||
>things : Val[]
|
||||
|
||||
for (const thing of things) {
|
||||
>thing : Val
|
||||
>things : Val[]
|
||||
|
||||
if (isNumVal(thing)) {
|
||||
>isNumVal(thing) : boolean
|
||||
>isNumVal : (x: Val) => x is NumVal
|
||||
>thing : Val
|
||||
|
||||
const { val } = thing;
|
||||
>val : number
|
||||
>thing : NumVal
|
||||
|
||||
val.toFixed(2);
|
||||
>val.toFixed(2) : string
|
||||
>val.toFixed : (fractionDigits?: number | undefined) => string
|
||||
>val : number
|
||||
>toFixed : (fractionDigits?: number | undefined) => string
|
||||
>2 : 2
|
||||
}
|
||||
else {
|
||||
const { val } = thing;
|
||||
>val : string
|
||||
>thing : StrVal
|
||||
|
||||
val.length;
|
||||
>val.length : number
|
||||
>val : string
|
||||
>length : number
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ type AProp<T extends { a: string }> = T
|
||||
>a : string
|
||||
|
||||
declare function myBug<
|
||||
>myBug : <T extends { [K in keyof T]: T[K]; }>(arg: T) => T
|
||||
>myBug : <T extends { [K in keyof T]: T[K] extends infer U ? U : never; }>(arg: T) => T
|
||||
|
||||
T extends { [K in keyof T]: T[K] extends AProp<infer U> ? U : never }
|
||||
>(arg: T): T
|
||||
@@ -24,7 +24,7 @@ declare function myBug<
|
||||
const out = myBug({obj1: {a: "test"}})
|
||||
>out : { obj1: { a: string; }; }
|
||||
>myBug({obj1: {a: "test"}}) : { obj1: { a: string; }; }
|
||||
>myBug : <T extends { [K in keyof T]: T[K]; }>(arg: T) => T
|
||||
>myBug : <T extends { [K in keyof T]: T[K] extends infer U ? U : never; }>(arg: T) => T
|
||||
>{obj1: {a: "test"}} : { obj1: { a: string; }; }
|
||||
>obj1 : { a: string; }
|
||||
>{a: "test"} : { a: string; }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(9,18): error TS2322: Type '{ forword: string; }' is not assignable to type 'Book'.
|
||||
Object literal may only specify known properties, but 'forword' does not exist in type 'Book'. Did you mean to write 'foreword'?
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(11,27): error TS2322: Type '{ foreward: string; }' is not assignable to type 'string | Book'.
|
||||
Object literal may only specify known properties, and 'foreward' does not exist in type 'string | Book'.
|
||||
Object literal may only specify known properties, but 'foreward' does not exist in type 'Book'. Did you mean to write 'foreword'?
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(13,53): error TS2322: Type '({ foreword: string; } | { forwards: string; })[]' is not assignable to type 'Book | Book[]'.
|
||||
Type '({ foreword: string; } | { forwards: string; })[]' is not assignable to type 'Book[]'.
|
||||
Type '{ foreword: string; } | { forwards: string; }' is not assignable to type 'Book'.
|
||||
@@ -13,17 +13,27 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(17,26): error TS2322: Type
|
||||
Object literal may only specify known properties, but 'foreward' does not exist in type 'Book & Cover'. Did you mean to write 'foreword'?
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(19,57): error TS2322: Type '{ foreword: string; color: string; price: number; }' is not assignable to type 'Book & Cover'.
|
||||
Object literal may only specify known properties, and 'price' does not exist in type 'Book & Cover'.
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(21,43): error TS2322: Type '{ foreword: string; price: number; }' is not assignable to type 'Book & number'.
|
||||
Object literal may only specify known properties, and 'price' does not exist in type 'Book & number'.
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(21,5): error TS2322: Type '{ foreword: string; price: number; }' is not assignable to type 'Book & number'.
|
||||
Type '{ foreword: string; price: number; }' is not assignable to type 'number'.
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(23,29): error TS2322: Type '{ couleur: string; }' is not assignable to type 'Cover | Cover[]'.
|
||||
Object literal may only specify known properties, and 'couleur' does not exist in type 'Cover | Cover[]'.
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(25,27): error TS2322: Type '{ forewarned: string; }' is not assignable to type 'Book | Book[]'.
|
||||
Object literal may only specify known properties, and 'forewarned' does not exist in type 'Book | Book[]'.
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(33,27): error TS2322: Type '{ colour: string; }' is not assignable to type 'Cover'.
|
||||
Object literal may only specify known properties, but 'colour' does not exist in type 'Cover'. Did you mean to write 'color'?
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(37,25): error TS2304: Cannot find name 'IFoo'.
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(39,11): error TS2322: Type '{ name: string; }' is not assignable to type 'T'.
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(41,11): error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type 'T & { prop: boolean; }'.
|
||||
Type '{ name: string; prop: boolean; }' is not assignable to type 'T'.
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(43,43): error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type 'T | { prop: boolean; }'.
|
||||
Object literal may only specify known properties, and 'name' does not exist in type '{ prop: boolean; }'.
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(45,76): error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type '{ name: string; } | (T & { prop: boolean; })'.
|
||||
Object literal may only specify known properties, and 'prop' does not exist in type '{ name: string; }'.
|
||||
tests/cases/compiler/objectLiteralExcessProperties.ts(49,44): error TS2322: Type '{ z: string; }' is not assignable to type 'object & { x: string; }'.
|
||||
Object literal may only specify known properties, and 'z' does not exist in type 'object & { x: string; }'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/objectLiteralExcessProperties.ts (10 errors) ====
|
||||
==== tests/cases/compiler/objectLiteralExcessProperties.ts (16 errors) ====
|
||||
interface Book {
|
||||
foreword: string;
|
||||
}
|
||||
@@ -40,7 +50,7 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(33,27): error TS2322: Type
|
||||
var b2: Book | string = { foreward: "nope" };
|
||||
~~~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '{ foreward: string; }' is not assignable to type 'string | Book'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'foreward' does not exist in type 'string | Book'.
|
||||
!!! error TS2322: Object literal may only specify known properties, but 'foreward' does not exist in type 'Book'. Did you mean to write 'foreword'?
|
||||
|
||||
var b3: Book | (Book[]) = [{ foreword: "hello" }, { forwards: "back" }];
|
||||
~~~~~~~~~~~~~~~~
|
||||
@@ -66,9 +76,9 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(33,27): error TS2322: Type
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'price' does not exist in type 'Book & Cover'.
|
||||
|
||||
var b7: Book & number = { foreword: "hi", price: 10.99 };
|
||||
~~~~~~~~~~~~
|
||||
~~
|
||||
!!! error TS2322: Type '{ foreword: string; price: number; }' is not assignable to type 'Book & number'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'price' does not exist in type 'Book & number'.
|
||||
!!! error TS2322: Type '{ foreword: string; price: number; }' is not assignable to type 'number'.
|
||||
|
||||
var b8: Cover | Cover[] = { couleur : "non" };
|
||||
~~~~~~~~~~~~~~~
|
||||
@@ -91,4 +101,37 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(33,27): error TS2322: Type
|
||||
!!! error TS2322: Type '{ colour: string; }' is not assignable to type 'Cover'.
|
||||
!!! error TS2322: Object literal may only specify known properties, but 'colour' does not exist in type 'Cover'. Did you mean to write 'color'?
|
||||
!!! related TS6501 tests/cases/compiler/objectLiteralExcessProperties.ts:28:5: The expected type comes from this index signature.
|
||||
|
||||
// Repros inspired by #28752
|
||||
|
||||
function test<T extends IFoo>() {
|
||||
~~~~
|
||||
!!! error TS2304: Cannot find name 'IFoo'.
|
||||
// No excess property checks on generic types
|
||||
const obj1: T = { name: "test" };
|
||||
~~~~
|
||||
!!! error TS2322: Type '{ name: string; }' is not assignable to type 'T'.
|
||||
// No excess property checks on intersections involving generics
|
||||
const obj2: T & { prop: boolean } = { name: "test", prop: true };
|
||||
~~~~
|
||||
!!! error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type 'T & { prop: boolean; }'.
|
||||
!!! error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type 'T'.
|
||||
// Excess property checks only on non-generic parts of unions
|
||||
const obj3: T | { prop: boolean } = { name: "test", prop: true };
|
||||
~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type 'T | { prop: boolean; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ prop: boolean; }'.
|
||||
// Excess property checks only on non-generic parts of unions
|
||||
const obj4: T & { prop: boolean } | { name: string } = { name: "test", prop: true };
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type '{ name: string; } | (T & { prop: boolean; })'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'prop' does not exist in type '{ name: string; }'.
|
||||
// No excess property checks when union includes 'object' type
|
||||
const obj5: object | { x: string } = { z: 'abc' }
|
||||
// The 'object' type has no effect on intersections
|
||||
const obj6: object & { x: string } = { z: 'abc' }
|
||||
~~~~~~~~
|
||||
!!! error TS2322: Type '{ z: string; }' is not assignable to type 'object & { x: string; }'.
|
||||
!!! error TS2322: Object literal may only specify known properties, and 'z' does not exist in type 'object & { x: string; }'.
|
||||
}
|
||||
|
||||
@@ -32,6 +32,23 @@ interface Indexed {
|
||||
var b10: Indexed = { 0: { }, '1': { } }; // ok
|
||||
|
||||
var b11: Indexed = { 0: { colour: "blue" } }; // nested object literal still errors
|
||||
|
||||
// Repros inspired by #28752
|
||||
|
||||
function test<T extends IFoo>() {
|
||||
// No excess property checks on generic types
|
||||
const obj1: T = { name: "test" };
|
||||
// No excess property checks on intersections involving generics
|
||||
const obj2: T & { prop: boolean } = { name: "test", prop: true };
|
||||
// Excess property checks only on non-generic parts of unions
|
||||
const obj3: T | { prop: boolean } = { name: "test", prop: true };
|
||||
// Excess property checks only on non-generic parts of unions
|
||||
const obj4: T & { prop: boolean } | { name: string } = { name: "test", prop: true };
|
||||
// No excess property checks when union includes 'object' type
|
||||
const obj5: object | { x: string } = { z: 'abc' }
|
||||
// The 'object' type has no effect on intersections
|
||||
const obj6: object & { x: string } = { z: 'abc' }
|
||||
}
|
||||
|
||||
|
||||
//// [objectLiteralExcessProperties.js]
|
||||
@@ -46,3 +63,18 @@ var b8 = { couleur: "non" };
|
||||
var b9 = { forewarned: "still no" };
|
||||
var b10 = { 0: {}, '1': {} }; // ok
|
||||
var b11 = { 0: { colour: "blue" } }; // nested object literal still errors
|
||||
// Repros inspired by #28752
|
||||
function test() {
|
||||
// No excess property checks on generic types
|
||||
var obj1 = { name: "test" };
|
||||
// No excess property checks on intersections involving generics
|
||||
var obj2 = { name: "test", prop: true };
|
||||
// Excess property checks only on non-generic parts of unions
|
||||
var obj3 = { name: "test", prop: true };
|
||||
// Excess property checks only on non-generic parts of unions
|
||||
var obj4 = { name: "test", prop: true };
|
||||
// No excess property checks when union includes 'object' type
|
||||
var obj5 = { z: 'abc' };
|
||||
// The 'object' type has no effect on intersections
|
||||
var obj6 = { z: 'abc' };
|
||||
}
|
||||
|
||||
@@ -90,3 +90,53 @@ var b11: Indexed = { 0: { colour: "blue" } }; // nested object literal still err
|
||||
>0 : Symbol(0, Decl(objectLiteralExcessProperties.ts, 32, 20))
|
||||
>colour : Symbol(colour, Decl(objectLiteralExcessProperties.ts, 32, 25))
|
||||
|
||||
// Repros inspired by #28752
|
||||
|
||||
function test<T extends IFoo>() {
|
||||
>test : Symbol(test, Decl(objectLiteralExcessProperties.ts, 32, 45))
|
||||
>T : Symbol(T, Decl(objectLiteralExcessProperties.ts, 36, 14))
|
||||
|
||||
// No excess property checks on generic types
|
||||
const obj1: T = { name: "test" };
|
||||
>obj1 : Symbol(obj1, Decl(objectLiteralExcessProperties.ts, 38, 9))
|
||||
>T : Symbol(T, Decl(objectLiteralExcessProperties.ts, 36, 14))
|
||||
>name : Symbol(name, Decl(objectLiteralExcessProperties.ts, 38, 21))
|
||||
|
||||
// No excess property checks on intersections involving generics
|
||||
const obj2: T & { prop: boolean } = { name: "test", prop: true };
|
||||
>obj2 : Symbol(obj2, Decl(objectLiteralExcessProperties.ts, 40, 9))
|
||||
>T : Symbol(T, Decl(objectLiteralExcessProperties.ts, 36, 14))
|
||||
>prop : Symbol(prop, Decl(objectLiteralExcessProperties.ts, 40, 21))
|
||||
>name : Symbol(name, Decl(objectLiteralExcessProperties.ts, 40, 41))
|
||||
>prop : Symbol(prop, Decl(objectLiteralExcessProperties.ts, 40, 55))
|
||||
|
||||
// Excess property checks only on non-generic parts of unions
|
||||
const obj3: T | { prop: boolean } = { name: "test", prop: true };
|
||||
>obj3 : Symbol(obj3, Decl(objectLiteralExcessProperties.ts, 42, 9))
|
||||
>T : Symbol(T, Decl(objectLiteralExcessProperties.ts, 36, 14))
|
||||
>prop : Symbol(prop, Decl(objectLiteralExcessProperties.ts, 42, 21))
|
||||
>name : Symbol(name, Decl(objectLiteralExcessProperties.ts, 42, 41))
|
||||
>prop : Symbol(prop, Decl(objectLiteralExcessProperties.ts, 42, 55))
|
||||
|
||||
// Excess property checks only on non-generic parts of unions
|
||||
const obj4: T & { prop: boolean } | { name: string } = { name: "test", prop: true };
|
||||
>obj4 : Symbol(obj4, Decl(objectLiteralExcessProperties.ts, 44, 9))
|
||||
>T : Symbol(T, Decl(objectLiteralExcessProperties.ts, 36, 14))
|
||||
>prop : Symbol(prop, Decl(objectLiteralExcessProperties.ts, 44, 21))
|
||||
>name : Symbol(name, Decl(objectLiteralExcessProperties.ts, 44, 41))
|
||||
>name : Symbol(name, Decl(objectLiteralExcessProperties.ts, 44, 60))
|
||||
>prop : Symbol(prop, Decl(objectLiteralExcessProperties.ts, 44, 74))
|
||||
|
||||
// No excess property checks when union includes 'object' type
|
||||
const obj5: object | { x: string } = { z: 'abc' }
|
||||
>obj5 : Symbol(obj5, Decl(objectLiteralExcessProperties.ts, 46, 9))
|
||||
>x : Symbol(x, Decl(objectLiteralExcessProperties.ts, 46, 26))
|
||||
>z : Symbol(z, Decl(objectLiteralExcessProperties.ts, 46, 42))
|
||||
|
||||
// The 'object' type has no effect on intersections
|
||||
const obj6: object & { x: string } = { z: 'abc' }
|
||||
>obj6 : Symbol(obj6, Decl(objectLiteralExcessProperties.ts, 48, 9))
|
||||
>x : Symbol(x, Decl(objectLiteralExcessProperties.ts, 48, 26))
|
||||
>z : Symbol(z, Decl(objectLiteralExcessProperties.ts, 48, 42))
|
||||
}
|
||||
|
||||
|
||||
@@ -98,3 +98,63 @@ var b11: Indexed = { 0: { colour: "blue" } }; // nested object literal still err
|
||||
>colour : string
|
||||
>"blue" : "blue"
|
||||
|
||||
// Repros inspired by #28752
|
||||
|
||||
function test<T extends IFoo>() {
|
||||
>test : <T extends any>() => void
|
||||
|
||||
// No excess property checks on generic types
|
||||
const obj1: T = { name: "test" };
|
||||
>obj1 : T
|
||||
>{ name: "test" } : { name: string; }
|
||||
>name : string
|
||||
>"test" : "test"
|
||||
|
||||
// No excess property checks on intersections involving generics
|
||||
const obj2: T & { prop: boolean } = { name: "test", prop: true };
|
||||
>obj2 : T & { prop: boolean; }
|
||||
>prop : boolean
|
||||
>{ name: "test", prop: true } : { name: string; prop: boolean; }
|
||||
>name : string
|
||||
>"test" : "test"
|
||||
>prop : boolean
|
||||
>true : true
|
||||
|
||||
// Excess property checks only on non-generic parts of unions
|
||||
const obj3: T | { prop: boolean } = { name: "test", prop: true };
|
||||
>obj3 : T | { prop: boolean; }
|
||||
>prop : boolean
|
||||
>{ name: "test", prop: true } : { name: string; prop: boolean; }
|
||||
>name : string
|
||||
>"test" : "test"
|
||||
>prop : boolean
|
||||
>true : true
|
||||
|
||||
// Excess property checks only on non-generic parts of unions
|
||||
const obj4: T & { prop: boolean } | { name: string } = { name: "test", prop: true };
|
||||
>obj4 : { name: string; } | (T & { prop: boolean; })
|
||||
>prop : boolean
|
||||
>name : string
|
||||
>{ name: "test", prop: true } : { name: string; prop: boolean; }
|
||||
>name : string
|
||||
>"test" : "test"
|
||||
>prop : boolean
|
||||
>true : true
|
||||
|
||||
// No excess property checks when union includes 'object' type
|
||||
const obj5: object | { x: string } = { z: 'abc' }
|
||||
>obj5 : object | { x: string; }
|
||||
>x : string
|
||||
>{ z: 'abc' } : { z: string; }
|
||||
>z : string
|
||||
>'abc' : "abc"
|
||||
|
||||
// The 'object' type has no effect on intersections
|
||||
const obj6: object & { x: string } = { z: 'abc' }
|
||||
>obj6 : object & { x: string; }
|
||||
>x : string
|
||||
>{ z: 'abc' } : { z: string; }
|
||||
>z : string
|
||||
>'abc' : "abc"
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
tests/cases/conformance/jsx/tsxIntrinsicAttributeErrors.tsx(29,2): error TS2322: Type '{ x: number; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<{ x: number; render(): void; }> & string'.
|
||||
Property 'x' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<{ x: number; render(): void; }> & string'.
|
||||
tests/cases/conformance/jsx/tsxIntrinsicAttributeErrors.tsx(29,2): error TS2741: Property 'key' is missing in type '{ x: number; }' but required in type 'IntrinsicAttributes'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/tsxIntrinsicAttributeErrors.tsx (1 errors) ====
|
||||
@@ -33,6 +32,6 @@ tests/cases/conformance/jsx/tsxIntrinsicAttributeErrors.tsx(29,2): error TS2322:
|
||||
var E: I;
|
||||
<E x={10} />
|
||||
~
|
||||
!!! error TS2322: Type '{ x: number; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<{ x: number; render(): void; }> & string'.
|
||||
!!! error TS2322: Property 'x' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<{ x: number; render(): void; }> & string'.
|
||||
!!! error TS2741: Property 'key' is missing in type '{ x: number; }' but required in type 'IntrinsicAttributes'.
|
||||
!!! related TS2728 tests/cases/conformance/jsx/tsxIntrinsicAttributeErrors.tsx:7:9: 'key' is declared here.
|
||||
|
||||
@@ -76,7 +76,7 @@ type T31<T> = T extends unknown ? true : false; // Deferred (so it distributes)
|
||||
>false : false
|
||||
|
||||
type T32<T> = never extends T ? true : false; // true
|
||||
>T32 : true
|
||||
>T32 : T32<T>
|
||||
>true : true
|
||||
>false : false
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// @strict: true
|
||||
|
||||
// Repro from #28758
|
||||
|
||||
interface NumVal { val: number; }
|
||||
interface StrVal { val: string; }
|
||||
type Val = NumVal | StrVal;
|
||||
|
||||
function isNumVal(x: Val): x is NumVal {
|
||||
return typeof x.val === 'number';
|
||||
}
|
||||
|
||||
function foo(things: Val[]): void {
|
||||
for (const thing of things) {
|
||||
if (isNumVal(thing)) {
|
||||
const { val } = thing;
|
||||
val.toFixed(2);
|
||||
}
|
||||
else {
|
||||
const { val } = thing;
|
||||
val.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,3 +31,20 @@ interface Indexed {
|
||||
var b10: Indexed = { 0: { }, '1': { } }; // ok
|
||||
|
||||
var b11: Indexed = { 0: { colour: "blue" } }; // nested object literal still errors
|
||||
|
||||
// Repros inspired by #28752
|
||||
|
||||
function test<T extends IFoo>() {
|
||||
// No excess property checks on generic types
|
||||
const obj1: T = { name: "test" };
|
||||
// No excess property checks on intersections involving generics
|
||||
const obj2: T & { prop: boolean } = { name: "test", prop: true };
|
||||
// Excess property checks only on non-generic parts of unions
|
||||
const obj3: T | { prop: boolean } = { name: "test", prop: true };
|
||||
// Excess property checks only on non-generic parts of unions
|
||||
const obj4: T & { prop: boolean } | { name: string } = { name: "test", prop: true };
|
||||
// No excess property checks when union includes 'object' type
|
||||
const obj5: object | { x: string } = { z: 'abc' }
|
||||
// The 'object' type has no effect on intersections
|
||||
const obj6: object & { x: string } = { z: 'abc' }
|
||||
}
|
||||
|
||||
@@ -147,3 +147,46 @@ type B2<T, V> =
|
||||
|
||||
type C2<T, V, E> =
|
||||
T extends object ? { [Q in keyof T]: C2<T[Q], V, E>; } : T;
|
||||
|
||||
// Repro from #28654
|
||||
|
||||
type MaybeTrue<T extends { b: boolean }> = true extends T["b"] ? "yes" : "no";
|
||||
|
||||
type T0 = MaybeTrue<{ b: never }> // "no"
|
||||
type T1 = MaybeTrue<{ b: false }>; // "no"
|
||||
type T2 = MaybeTrue<{ b: true }>; // "yes"
|
||||
type T3 = MaybeTrue<{ b: boolean }>; // "yes"
|
||||
|
||||
// Repro from #28824
|
||||
|
||||
type Union = 'a' | 'b';
|
||||
type Product<A extends Union, B> = { f1: A, f2: B};
|
||||
type ProductUnion = Product<'a', 0> | Product<'b', 1>;
|
||||
|
||||
// {a: "b"; b: "a"}
|
||||
type UnionComplement = {
|
||||
[K in Union]: Exclude<Union, K>
|
||||
};
|
||||
type UCA = UnionComplement['a'];
|
||||
type UCB = UnionComplement['b'];
|
||||
|
||||
// {a: "a"; b: "b"}
|
||||
type UnionComplementComplement = {
|
||||
[K in Union]: Exclude<Union, Exclude<Union, K>>
|
||||
};
|
||||
type UCCA = UnionComplementComplement['a'];
|
||||
type UCCB = UnionComplementComplement['b'];
|
||||
|
||||
// {a: Product<'b', 1>; b: Product<'a', 0>}
|
||||
type ProductComplement = {
|
||||
[K in Union]: Exclude<ProductUnion, { f1: K }>
|
||||
};
|
||||
type PCA = ProductComplement['a'];
|
||||
type PCB = ProductComplement['b'];
|
||||
|
||||
// {a: Product<'a', 0>; b: Product<'b', 1>}
|
||||
type ProductComplementComplement = {
|
||||
[K in Union]: Exclude<ProductUnion, Exclude<ProductUnion, { f1: K }>>
|
||||
};
|
||||
type PCCA = ProductComplementComplement['a'];
|
||||
type PCCB = ProductComplementComplement['b'];
|
||||
|
||||
Reference in New Issue
Block a user