Reputation: 63
I am creating a matrix / 2d array of booleans and I want to infer a type that isn't simply "ANY" for dategrid.
let yearRange = [2000,2001,2002,2003,2004];
let monthRange = [0,1,2,3,4,5,6,7,8,9,10,11];
let dateGrid = any;
yearRange.forEach((year) => {
monthRange.forEach((month) => {
dateGrid[year][month] = true;
});
});
How does one create an interface / type for dategrid that:
Infers the structure: e.g. dateGrid[yearIndex][possibleMonthValues]:boolean And restricts the months index to only the applicable months.
dateGrid[2000][0] = true
dateGrid[2000][1] = true
dateGrid[2000][2] = true
dateGrid[2000][3] = true
dateGrid[2000][4] = true
dateGrid[2000][5] = true
dateGrid[2000][6] = true
dateGrid[2000][7] = true
dateGrid[2000][8] = true
dateGrid[2000][9] = true
dateGrid[2000][10] = true
dateGrid[2000][11] = true
dateGrid[2001][0] = true
... and so on ...
Upvotes: 3
Views: 451
Reputation: 20132
To be totally strict we can infer the proper narrowed types from variables you have given by using const
keyword. As I assume years are only example, so the sweet spot would be only restrict months, and leave years as number
:
// use const in order to get proper types
let yearRange = [2000,2001,2002,2003,2004];
let monthRange = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] as const;
type Month = typeof monthRange[number];
let dateGrid: Record <number,Record<Month, boolean>>;
Record<Month, boolean>
will be good idea if we restrict to have all months from 0 to 11. If we allow on only part of months in the year we can create non-exlusive Record:
let dateGrid: Record<number, Partial<Record<Month, boolean>>> = {
[2000]: {
"0" : false
}
} // valid as not all fields needs to be provided
const a = dateGrid[2000][4] // boolean | undefined
// in contrary exclusive type
let dateGridExclusive: Record<number, Record<Month, boolean>> = {
[2000]: {
"0" : false
}
} // error all months need to be provided
const b = dateGrid[2000][4] // boolean
Pay attention that I have used Partial
utility type in order to loose the constraint and allow on part of months to be provided.
If we want to use this as array we can perform another array type consider:
type Months = [
boolean,
boolean,
boolean,
boolean,
boolean,
boolean,
boolean,
boolean,
boolean,
boolean,
boolean,
boolean,
]
let dateGrid: Months[] // array of 12 element tuples
The minus of using array at year level is that when we set start point of such from 2000, we have 1999 undefined values.
Upvotes: 1