3

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 ...

1 Answer 1

1

Record based solution

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.


Array based solution

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Beautiful. Nicely done! and you are correct in your assumption on years. Now the only issue I can see here is I can no longer treat dateGrid as an 'array' e.g. (dateGrid.flat().indexOf(false) !== -1);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.