Merge pull request #28942 from Microsoft/missing3.2Prs

Port missing 3.2 PRs
This commit is contained in:
Daniel Rosenwasser
2018-12-10 13:46:31 -08:00
committed by GitHub
19 changed files with 855 additions and 50 deletions
+47 -32
View File
@@ -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.
+1 -1
View File
@@ -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'];