Closed
Description
TypeScript Version:
3.3.1
Search Terms:
conditional types default
Code
// A *self-contained* demonstration of the problem follows...
// Test this by running `tsc` on the command-line, rather than through another build tool such as Gulp, Webpack, etc.
I want to give the user the ability to supply their own interface or default to a different structure:
export interface Config {
[key: string]:
| number[]
| string[]
| number
| string
}
export type AddArrayLike<T> = unknown extends T ? Config | Config[] : {
[P in keyof T]: T[P] | T[P][]
}
export interface INodeGroupProps<T = unknown, State = unknown> {
data: T[];
keyAccessor: (data: T, index: number) => string | number;
start: (data: T, index: number) => unknown extends State ? Config : State;
enter?: (data: T, index: number) => AddArrayLike<State>;
update?: (data: T, index: number) => AddArrayLike<State>;
leave?: (data: T, index: number) => AddArrayLike<State>;
}
So I have a State type argument that defaults to unknown. If it is unknown then it should be Config.
Everything works fine in this example of supplying your own State.
export type Point = {x: number, y: number};
export interface NodesState {
top: number;
left: number;
opacity: number;
}
const points: Point[] = [
{x: 0, y: 0},
{x: 1, y: 2},
{x: 2, y: 3}
]
const Test: INodeGroupProps<Point, NodesState> = {
data: points,
keyAccessor: (d) => {
return d.x
},
start: (point) => {
return {
top: point.y,
left: point.x,
opacity: 0
};
},
enter: (point) => {
return {
top: [point.y],
left: [point.x],
opacity: [0]
};
},
update: (point) => {
return {
top: [point.y],
left: [point.x],
opacity: 0
};
},
leave: (point) => {
return {
top: [point.y],
left: [point.x],
opacity: 0
};
},
};
I get type safety if I change one of the types from the NodeState interface to be not a number, e.g.
return {
top,
left,
opacity: true
};
But if I add a prop that is not part of the NodeState interface then this is not recognised as a break.
e.g.
return {
top,
left,
opacity: 0,
fook: 'blah' // not part of NodeState
};
Expected behavior:
fook
should be identified as not part of the NodeState
interface
Actual behavior:
No type error
Playground Link:
Related Issues: