Skip to content

Commit

Permalink
feat(array): expose ArrayWith type declaration
Browse files Browse the repository at this point in the history
  • Loading branch information
uladkasach committed Aug 18, 2024
1 parent 795cffa commit 7855ac5
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
35 changes: 35 additions & 0 deletions src/types/ArrayWith.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { given, then, when } from 'test-fns';

describe('ArrayWith', () => {
given('desire for array with min length', () => {
then('we can declare the type', () => {
let products: ArrayWith<'min', 1, string>;
});
then('it allows arrays of exactly the min length to it', () => {
const products: ArrayWith<'min', 1, string> = ['doughnut']; // 🍩
});
then('it allows arrays with more than the min length to it', () => {
const products: ArrayWith<'min', 1, string> = ['doughnut', 'waffle']; // 🍩, 🧇
});
then('it blocks arrays with less than the min length to it', () => {
// @ts-expect-error; Type '[]' is not assignable to type '[string, ...string[]]'. Source has 0 element(s) but target requires 1.ts(2322)
const products: ArrayWith<'min', 1, string> = []; // 🍩, 🧇
});
});
given('desire for array with exact length', () => {
then('we can declare the type', () => {
let products: ArrayWith<'len', 1, string>;
});
then('it allows arrays of exactly the desired length to it', () => {
const products: ArrayWith<'len', 1, string> = ['doughnut']; // 🍩
});
then('it allows arrays with more than the desired length to it', () => {
// @ts-expect-error; Type '[string, string]' is not assignable to type '[string]'.Source has 2 element(s) but target allows only 1.
const products: ArrayWith<'len', 1, string> = ['doughnut', 'waffle']; // 🍩, 🧇
});
then('it blocks arrays with less than the desired length to it', () => {
// @ts-expect-error; Type '[]' is not assignable to type '[string]'. Source has 0 element(s) but target requires 1.ts(2322)
const products: ArrayWith<'len', 1, string> = [];
});
});
});
24 changes: 24 additions & 0 deletions src/types/ArrayWith.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* ref:
* - https://stackoverflow.com/a/67655609/3068233
* - https://stackoverflow.com/a/73409753/3068233
*/
type BuildArrayWith<
TCheck extends 'len' | 'min', // todo: support 'max' too?
TLength extends number,
TType,
TCurrent extends TType[],
> = TCurrent['length'] extends TLength
? TCheck extends 'len'
? [...TCurrent]
: [...TCurrent, ...TType[]]
: BuildArrayWith<TCheck, TLength, TType, [...TCurrent, TType]>;

/**
* declares a type of array with a check on its length
*/
type ArrayWith<
TCheck extends 'len' | 'min', // todo: support 'max' too?
TLength extends number,
TType,
> = BuildArrayWith<TCheck, TLength, TType, []>;

0 comments on commit 7855ac5

Please sign in to comment.