Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(@angular-ru/common): item functions type #684

Merged
merged 10 commits into from
Jun 20, 2021
6 changes: 3 additions & 3 deletions packages/common/array/src/take-first-item.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Nullable } from '@angular-ru/common/typings';
import { Nullable, TupleItem } from '@angular-ru/common/typings';

export function takeFirstItem<T>(array?: Nullable<T[]>): Nullable<T> {
return array?.[0];
export function takeFirstItem<ArrayType extends Nullable<unknown[]>>(array: ArrayType): TupleItem<ArrayType, 0> {
return (Array.isArray(array) ? array[0] : undefined) as TupleItem<ArrayType, 0>;
}
6 changes: 3 additions & 3 deletions packages/common/array/src/take-last-item.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Nullable } from '@angular-ru/common/typings';
import { LastOfTuple, Nullable } from '@angular-ru/common/typings';

export function takeLastItem<T>(array?: Nullable<T[]>): Nullable<T> {
return array?.[array?.length - 1];
export function takeLastItem<ArrayType extends Nullable<unknown[]>>(array: ArrayType): LastOfTuple<ArrayType> {
return (Array.isArray(array) ? array[array.length - 1] : undefined) as LastOfTuple<ArrayType>;
}
6 changes: 3 additions & 3 deletions packages/common/array/src/take-second-item.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Nullable } from '@angular-ru/common/typings';
import { Nullable, TupleItem } from '@angular-ru/common/typings';

export function takeSecondItem<T>(array?: Nullable<T[]>): Nullable<T> {
return array?.[1];
export function takeSecondItem<ArrayType extends Nullable<unknown[]>>(array: ArrayType): TupleItem<ArrayType, 1> {
return (Array.isArray(array) ? array[1] : undefined) as TupleItem<ArrayType, 1>;
}
12 changes: 8 additions & 4 deletions packages/common/array/src/take-third-item.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Nullable } from '@angular-ru/common/typings';
import { Nullable, TupleItem } from '@angular-ru/common/typings';

export function takeThirdItem<T>(array?: Nullable<T[]>): Nullable<T> {
const thirdItemIndex: number = 2;
return array?.[thirdItemIndex];
type ThirdItemIndex = 2;
const thirdItemIndex: ThirdItemIndex = 2;

export function takeThirdItem<ArrayType extends Nullable<unknown[]>>(
array: ArrayType
): TupleItem<ArrayType, ThirdItemIndex> {
return (Array.isArray(array) ? array[thirdItemIndex] : undefined) as TupleItem<ArrayType, ThirdItemIndex>;
}
40 changes: 40 additions & 0 deletions packages/common/docs/typings.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,43 @@ function makeSomeOperations(form: FormGroup, descriptor: DateIntervalDescriptor)
// ...
}
```

- `Tuple`

```ts
type NumberCouple = Tuple<number, 2>; // [number, number]
type Number4 = Tuple<number, 4>; // [number, number, number, number]
type BracedString = Tuple<string>; // [string]
type NumberCouple = Tuple<string, 0>; // []
```

- `InfiniteTuple`

```ts
type CoupleAndMaybeSomeNumbers = InfiniteTuple<number, 2>; // [number, number, ...number]
type AtLeast4Numbers = InfiniteTuple<number, 4>; // [number, number, number, number, ...number]
type AtLeastOneLine = InfiniteTuple<string>; // [string, ...string]
type SomeLines = InfiniteTuple<string, 0>; // string[]
```

- `LastOfTuple`

```ts
type Number = LastOfTuple<[number]>; // number
type MaybeString = LastOfTuple<string[]>; // string | undefined
type Boolean = LastOfTuple<[string, boolean]>; // boolean
type StringOrNumber = LastOfTuple<[string, ...number[]]>; // string | number
type Nothing = LastOfTuple<[]>; // undefined
```

- `TupleItem`

```ts
type Number = TupleItem<[number], 0>; // number
type MaybeString = TupleItem<string[], 1>; // string | undefined
type Boolean = TupleItem<[string, boolean], 1>; // boolean
type String = TupleItem<[string, ...number[]], 0>; // string
type MaybeNumber = TupleItem<[string, ...number[]], 3>; // number | undefined
type Nothing = TupleItem<[], 0>; // undefined
type NothingToo = TupleItem<[], 3>; // undefined
```
3 changes: 3 additions & 0 deletions packages/common/typings/src/infinite-tuple.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Tuple } from './tuple';

export type InfiniteTuple<ItemType, Length extends number = 1> = [...Tuple<ItemType, Length>, ...ItemType[]];
7 changes: 7 additions & 0 deletions packages/common/typings/src/last-of-tuple.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type LastOfTuple<ArrayType> = ArrayType extends unknown[]
? ArrayType extends []
? undefined
: ArrayType extends [unknown, ...unknown[]]
? ArrayType[ArrayType extends [unknown, ...infer Rest] ? Rest['length'] : number]
: ArrayType[number] | undefined
: undefined;
4 changes: 4 additions & 0 deletions packages/common/typings/src/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ export { Descriptor } from './descriptor';
export { EmptyValue } from './empty-value';
export { Fn } from './fn';
export { Immutable, Mutable, PrimitiveType } from './immutability';
export { InfiniteTuple } from './infinite-tuple';
export { InputBoolean } from './input-boolean';
export { Join } from './join';
export { KeyOfList } from './key-of-list';
export { KeyValueComparator } from './key-value-comparator';
export { KeyboardKeys } from './keyboard';
export { KeysOfType } from './keys-of-type';
export { LastOfTuple } from './last-of-tuple';
export { Leaves } from './leaves';
export { NgCssClasses } from './ng-css-classes';
export { Nullable } from './nullable';
Expand All @@ -30,3 +32,5 @@ export { Resolver } from './resolver';
export { SortOrderType } from './sort-order-type';
export { StringValuesOfEnum } from './string-values-of-enum';
export { Timestamp } from './timestamp';
export { Tuple } from './tuple';
export { TupleItem } from './tuple-item';
7 changes: 7 additions & 0 deletions packages/common/typings/src/tuple-item.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { InfiniteTuple } from './infinite-tuple';

export type TupleItem<ArrayType, Index extends number> = ArrayType extends unknown[]
? ArrayType extends [unknown, ...InfiniteTuple<unknown, Index>]
? ArrayType[Index]
: ArrayType[Index] | undefined
: undefined;
3 changes: 3 additions & 0 deletions packages/common/typings/src/tuple.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type Tuple<ItemType, Length extends number = 1, Base extends unknown[] = []> = Base['length'] extends Length
Markiewic marked this conversation as resolved.
Show resolved Hide resolved
? Base
: Tuple<ItemType, Length, [ItemType, ...Base]>;