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
?