Here is a simple case that is easy in isolation, but breaks down when composed into a larger type.
If scrollToItem is defined, then getRowId must also be defined. Otherwise, getRowId is optional.
This type definition works just fine:
type ScrollProps<T> =
| { scrollToItem: T; getRowId: (row: T) => string; }
| { getRowId?: (row: T) => string; };
const a: ScrollProps<number> = {}; // ok
const b: ScrollProps<number> = { scrollToItem: 6, getRowId: (row) => '' }; // ok
const c: ScrollProps<number> = { getRowId: (row) => '' }; // ok
const d: ScrollProps<number> = { scrollToItem: 6 }; // error - expected
It can be extended further to pick the getRowId property from an imported library type.
type LibraryObject<T> = {
getRowId?: (row: T) => string;
otherProps?: boolean;
};
type ScrollProps<T> =
| ({ scrollToItem: T } & Required<Pick<LibraryObject<T>, 'getRowId'>>)
| Pick<LibraryObject<T>, 'getRowId'>;
const a: ScrollProps<number> = {}; // ok
const b: ScrollProps<number> = { scrollToItem: 6, getRowId: (row) => '' }; // ok
const c: ScrollProps<number> = { getRowId: (row) => '' }; // ok
const d: ScrollProps<number> = { scrollToItem: 6 }; // error - expected
Unfortunately, I have to add this type definition onto an existing type, which is already extending the library type. For some reason, TypeScript no longer requires getRowId when passing scrollToItem IF ALSO passing some of the other properties it extends.
type LibraryObject<T> = {
getRowId?: (row: T) => string;
otherProps?: boolean;
};
type ScrollProps<T> =
| ({ scrollToItem: T } & Required<Pick<LibraryObject<T>, 'getRowId'>>)
| Pick<LibraryObject<T>, 'getRowId'>;
type MasterType<T> = LibraryObject<T> & ScrollProps<T>;
const a: MasterType<number> = {}; // ok
const b: MasterType<number> = { scrollToItem: 6, getRowId: (row) => '' }; // ok
const c: MasterType<number> = { getRowId: (row) => '' }; // ok
const d: MasterType<number> = { scrollToItem: 6 }; // error - expected
const e: MasterType<number> = { scrollToItem: 6, otherProps: true }; // NO ERROR, but I wish there were!
Why would setting any of the other properties negate the required properties managed by ScrollProps?