Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No excess properties error in nested intersection type #13813

Closed
sktw opened this issue Feb 1, 2017 · 1 comment · Fixed by #30853
Closed

No excess properties error in nested intersection type #13813

sktw opened this issue Feb 1, 2017 · 1 comment · Fixed by #30853
Assignees
Labels
Bug A bug in TypeScript
Milestone

Comments

@sktw
Copy link

sktw commented Feb 1, 2017

TypeScript Version: 2.1.5

Code

interface A {
    x: string
}

interface B {
    a: A;
}

interface C {
    c: number;
}

type D = B & C;

let a: B = {a: {x: 'hello'}}; // ok
let b: B = {a: {x: 2}}; // error - types of property x are incompatible
let c: B = {a: {x: 'hello', y: 2}}; // error - y does not exist in type A

let d: D = {a: {x: 'hello'}, c: 5}; // ok
let e: D = {a: {x: 2}, c: 5}; // error - types of property x are incompatible
let f: D = {a: {x: 'hello', y: 2}, c: 5}; // should be an error?: y does not exist in type A

Expected behavior:
Excess property checking should cause a compiler error for the last example.

Actual behavior:
Last example compiles without error.

@sktw sktw changed the title No excess properties error in nested interface type No excess properties error in nested intersection type Feb 1, 2017
@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label May 24, 2017
@mattmccutchen
Copy link
Contributor

mattmccutchen commented Mar 20, 2018

I just ran into this bug and it is marked "Needs Investigation", so I thought I would provide some. As far as I can tell (with the caveat that TypeScript is really complicated and I'm a newbie), the problem is with the following code in isRelatedTo in checker.ts (the file is too big to link to a formatted version):

                if (isObjectLiteralType(source) && source.flags & TypeFlags.FreshLiteral) {
                    const discriminantType = target.flags & TypeFlags.Union ? findMatchingDiscriminantType(source, target as UnionType) : undefined;
                    if (hasExcessProperties(<FreshObjectLiteralType>source, target, discriminantType, reportErrors)) {
                        if (reportErrors) {
                            reportRelationError(headMessage, source, target);
                        }
                        return Ternary.False;
                    }
                    // Above we check for excess properties with respect to the entire target type. When union
                    // and intersection types are further deconstructed on the target side, we don't want to
                    // make the check again (as it might fail for a partial target type). Therefore we obtain
                    // the regular source type and proceed with that.
                    if (isUnionOrIntersectionTypeWithoutNullableConstituents(target) && !discriminantType) {
                        source = getRegularTypeOfObjectLiteral(source);
                    }
                }

After the code checks for excess properties only at the top level, getRegularTypeOfObjectLiteral disables the check recursively. Indeed, if a source type S can be successfully compared to a target type X & Y or X | Y by comparing S to X and/or Y individually, at no point during the recursive comparison to X or Y do we have all the information to do a correct check for excess properties in object literal types nested in S. So the least disruptive way I can think of to fix the problem is to change the code quoted above to do a recursive check for excess properties. Another option would be to declare the problem a design limitation.

@mhegazy mhegazy added Bug A bug in TypeScript and removed Needs Investigation This issue needs a team member to investigate its status. labels Mar 29, 2018
@mhegazy mhegazy added this to the TypeScript 2.9 milestone Mar 29, 2018
@mhegazy mhegazy modified the milestones: TypeScript 3.0, TypeScript 3.1 Jul 2, 2018
@sandersn sandersn modified the milestones: TypeScript 3.4.0, Backlog Mar 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants