Skip to content

Similar interfaces (multiple properties with the same names) get falsely mapped #35548

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

Closed
andreivanea opened this issue Dec 6, 2019 · 6 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@andreivanea
Copy link

TypeScript Version: 3.7.2

Search Terms: interfaces subset properties

Code

export interface MyFirstInterface {
    id: number;
    name: string;
}

export interface MySecondInterface {
    id: number;
    value: string;
    comment: string;
}

export interface MyThirdInterface {
    id: number;
    value: string;
    comment: string;
    enabled: boolean;
}

// first case: Promise
const getFirst = (): Promise<MyFirstInterface> => {
    return Promise.resolve(null as any);
}

const getSecond = (): Promise<MySecondInterface> => {
    return Promise.resolve(null as any);
}

const getThird = (): Promise<MyThirdInterface> => {
    return Promise.resolve(null as any);
}


const runAll = async () => {
    const data = await Promise.all([getFirst(), getSecond(), getThird()]);
    //data is [MyFirstInterface, MySecondInterface, MySecondInterface]
}

const runSome = async () => {
    const data = await Promise.all([getFirst(), getSecond()]);
}

// second case: Array
const f: MyFirstInterface = null as any;
const s: MySecondInterface = null as any;
const t: MyThirdInterface = null as any;
const a = [f, s, t];
//a is (MyFirstInterface | MySecondInterface)[]

Expected behavior:
data should be [MyFirstInterface, MySecondInterface, MyThirdInterface ]

Actual behavior:
data is [MyFirstInterface, MySecondInterface, MySecondInterface]

Playground Link:
https://www.typescriptlang.org/play/index.html?ssl=1&ssc=1&pln=47&pc=48#code/KYDwDg9gTgLgBASwHY2FAZgQwMbDgWQE8AxBKAZxgEkU0tc4BvAKDjcQBMAuOJAVwC2AIzQBuVuySYBwHpSjIA5uIC+zZqEixEtDDjxEAysGwQkHGqj0MW7Tj37CxEtgDdMAGz6y48peLtTARkUORgFJGVmNQ1waHhkK3oDQgAVAAsyC11kphd7XkERKAD2dy8fP0jStiCQmDCIqLtgKSEPYG44IQgIDswkVXUAemG4dDJKOGxMch8ABSgIAQQ55lMkKcVgGFIKeABeOAAKAEoeReXV4AAeIj3KSzp9AD44A7fbdigdvigkOCXFZzAB0P3IfVcwGO-A8HjgswRSEIpyG6zMWx2xg2HHeJ3OgKWwNuRhMZmySVe70++R+MD+AKB1zBwAhHihML4cIR5CRKLRG0xMAyWTxZwuROudzSmSgFOeuDeHzydjpDMJV1B4Mh0Nh8MRA350XU6M28CgfCQAEFuUdZoQkNh8dSVexBfAOJgYJg8ZgAO6YBDwJmgzweY4AbW2u0mMDOABo4NHseSE0mdiK5WcALqo-KjT3exC8iP3WNPazAROknEV5LVwgp8x1-TZ42mqYWpCGZZ4O3kB1Os4ur61DEer0+u0BoMa4kgsOR6MPOOnRPJsnmHN5mKjXyb3EzOY8K1QKCYQgd+DoHhl-YthhHPU8vnid2+W+Ng8PvuFbkG5E33HOAGgIGUsh-PFnwAwggLNBE8QjdBE3IRMYGzcRRh9VYTjvR4cn0OAAB8wKbeVK1OCNsyAA

The two interfaces, MySecondInterface and MyThirdInterface, are almost identical. All the properties from MySecondInterface ar found on MyThirdInterface but MyThirdInterface has at least one additional one. Due to (project) constraints extending MySecondInterface to build MyThirdInterface (does not work anyway) -- they represent basically different objects, but the have the same properties (not necessarily the ones in the example).

@andreivanea andreivanea changed the title Similar interfaces (multiple properties with the same names) get falsly mapped Similar interfaces (multiple properties with the same names) get falsely mapped Dec 6, 2019
@MartinJohns
Copy link
Contributor

Seems to be a duplicate of #34937.

@andreivanea
Copy link
Author

@MartinJohns yes, they seam to be related. It was mentioned in that issue that the types don't have to have explicit inheritance, which is exactly my use case.

However, please take a look at my Array example (second case). This does not appear to be confined to Promise.all.

@MartinJohns
Copy link
Contributor

Your second case behaves as it should, and it's unrelated to any interfaces. Type inference determines the best common type.

const a = 0;
const b = true;
const c = "";

const data = [a, b, c]; // Type is (number | boolean | string)[]

If you want the resulting type to be a tuple, then you can use a const context using the const keyword:

const a = 0;
const b = true;
const c = "";

const data = [a, b, c] as const; // Type is [number, boolean, string]

@andreivanea
Copy link
Author

Shouldn't the type of the array be resolved to (MyFirstInterface | MySecondInterface | MyThirdInterface)[] instead? It seams to me that the third type is being ignored (or maybe resolved to the second one), as in the case of Promise.all.

@RyanCavanaugh
Copy link
Member

If someone said "You can park either a car here, or a blue car", what they're describing is a parking spot for cars. "car or blue car" is a meaningless phrase.

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Dec 20, 2019
@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants