mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 12:08:41 -06:00
Add support for type parameters in isKnownProperty and create test case
Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
This commit is contained in:
parent
07bdeb7f86
commit
7adcf162bf
@ -22890,9 +22890,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return getUnionType(reduceLeft(types, appendPropType, /*initial*/ undefined) || emptyArray);
|
||||
}
|
||||
|
||||
function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean {
|
||||
if (!isExcessPropertyCheckTarget(target) || !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
|
||||
function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean {
|
||||
if (!isExcessPropertyCheckTarget(target) || !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
|
||||
}
|
||||
const isComparingJsxAttributes = !!(getObjectFlags(source) & ObjectFlags.JsxAttributes);
|
||||
if (
|
||||
@ -34263,32 +34263,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
* @param name a property name to search
|
||||
* @param isComparingJsxAttributes a boolean flag indicating whether we are searching in JsxAttributesType
|
||||
*/
|
||||
function isKnownProperty(targetType: Type, name: __String, isComparingJsxAttributes: boolean): boolean {
|
||||
if (targetType.flags & TypeFlags.Object) {
|
||||
// For backwards compatibility a symbol-named property is satisfied by a string index signature. This
|
||||
// is incorrect and inconsistent with element access expressions, where it is an error, so eventually
|
||||
// we should remove this exception.
|
||||
if (
|
||||
getPropertyOfObjectType(targetType, name) ||
|
||||
getApplicableIndexInfoForName(targetType, name) ||
|
||||
isLateBoundName(name) && getIndexInfoOfType(targetType, stringType) ||
|
||||
isComparingJsxAttributes && isHyphenatedJsxName(name)
|
||||
) {
|
||||
// For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (targetType.flags & TypeFlags.Substitution) {
|
||||
return isKnownProperty((targetType as SubstitutionType).baseType, name, isComparingJsxAttributes);
|
||||
}
|
||||
if (targetType.flags & TypeFlags.UnionOrIntersection && isExcessPropertyCheckTarget(targetType)) {
|
||||
for (const t of (targetType as UnionOrIntersectionType).types) {
|
||||
if (isKnownProperty(t, name, isComparingJsxAttributes)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
function isKnownProperty(targetType: Type, name: __String, isComparingJsxAttributes: boolean): boolean {
|
||||
if (targetType.flags & TypeFlags.Object) {
|
||||
// For backwards compatibility a symbol-named property is satisfied by a string index signature. This
|
||||
// is incorrect and inconsistent with element access expressions, where it is an error, so eventually
|
||||
// we should remove this exception.
|
||||
if (
|
||||
getPropertyOfObjectType(targetType, name) ||
|
||||
getApplicableIndexInfoForName(targetType, name) ||
|
||||
isLateBoundName(name) && getIndexInfoOfType(targetType, stringType) ||
|
||||
isComparingJsxAttributes && isHyphenatedJsxName(name)
|
||||
) {
|
||||
// For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (targetType.flags & TypeFlags.Substitution) {
|
||||
return isKnownProperty((targetType as SubstitutionType).baseType, name, isComparingJsxAttributes);
|
||||
}
|
||||
if (targetType.flags & TypeFlags.TypeParameter) {
|
||||
const constraint = getConstraintOfTypeParameter(targetType as TypeParameter);
|
||||
return constraint ? isKnownProperty(constraint, name, isComparingJsxAttributes) : false;
|
||||
}
|
||||
if (targetType.flags & TypeFlags.UnionOrIntersection && isExcessPropertyCheckTarget(targetType)) {
|
||||
for (const t of (targetType as UnionOrIntersectionType).types) {
|
||||
if (isKnownProperty(t, name, isComparingJsxAttributes)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isExcessPropertyCheckTarget(type: Type): boolean {
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
// Test case for destructuring assignment with generic constraints issue
|
||||
|
||||
type DataType = 'a' | 'b';
|
||||
|
||||
declare function foo<T extends { dataType: DataType }>(template: T): [T, any, any];
|
||||
declare function bar<T extends { dataType: DataType }>(template: T): [T, any];
|
||||
|
||||
function testDestructuringBug() {
|
||||
// These work fine (and should continue to work)
|
||||
const [, ,] = foo({ dataType: 'a', day: 0 });
|
||||
const [x, y, z] = foo({ dataType: 'a', day: 0 });
|
||||
const [,] = bar({ dataType: 'a', day: 0 });
|
||||
const [a, b] = bar({ dataType: 'a', day: 0 });
|
||||
|
||||
// These should work but currently don't (this is the bug)
|
||||
const [, , t] = foo({ dataType: 'a', day: 0 }); // Should not error
|
||||
const [, u] = bar({ dataType: 'a', day: 0 }); // Should not error
|
||||
|
||||
console.log(x, y, z, t, a, b, u);
|
||||
}
|
||||
|
||||
// Test that direct calls work fine (they do)
|
||||
function testDirectCalls() {
|
||||
const result1 = foo({ dataType: 'a', day: 0 });
|
||||
const result2 = bar({ dataType: 'a', day: 0 });
|
||||
console.log(result1, result2);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user