Please consider this example:
// all properties in Item should be optional, this is by design
type Item = {
id?: number
name?: string
}
interface WithVersion {
version: number
}
export type ResultType =
& WithVersion // #1 try to remove it
& {
version: number
list: Item[];
};
export interface Data {
list: Array<string>;
}
// As per my understanding, this function should not compile, because elem.list is not assignable to list in ResultType
const builder = <T extends Data>(data: Array<T>): ResultType[] => {
const result = data.map((elem) => ({
list: elem.list, // #2 list is string[], whereas ResultType expects list to be Item[]
version: 2,
}))
return result // #3
}
I am a bit confused by the assignability rules of TypeScript.
Try to remove WithVersion from ResultType. TypeScript will complain about the assignability of result to return type of builder function (ResultType).
Further more, if you define explicit return type for Array.prototype.map callback, TypeScript will complain just as I expect:
const builder = <T extends Data>(data: Array<T>): ResultType[] => {
const result = data.map((elem):ResultType => ({
list: elem.list, // error as expected
version: 2,
}))
return result
}
My questions are:
Why there is no error without explicit type for
mapcallback. It is clear thatstring[]is not assignable toItem[].declare let foo: string[] declare let bar: Item[] foo = bar bar = fooWhy does an error appear when I remove
WithVersionfrom theResultTypedefinition? It looks like that intersection ofWithVersionand{ version: number list: Item[]; }somehow affectsResultType, whereas in my opinion, this intersection should not affect it at all.
SIMPLIFIED VERSION
type Item = {
id?: number
name?: string
}
interface WithVersion {
version: number
}
export type ResultType =
& WithVersion // #1 try to remove it
& {
version: number
list: Item[];
};
declare let result: ResultType;
declare let list: string[];
let a = {
list,
version: 2,
};
result = a;
I have created an issue in TS repo