@telokys/ts-meta-types
v2.1.3
Published
Type helpers for TypeScript
Downloads
5
Readme
ts-meta-types
Collection of useful TypeScript helpers for manipulating or altering types.
- Install
- Usage
- API
Install
npm install -D @telokys/ts-meta-types
Usage
import { ReplaceType } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second: boolean;
third: string;
}
type MyNewData = ReplaceType<MyData, boolean, string>;
//=> interface MyNewData {
// first: number;
// second: string;
// third: string;
// }
API
Select keys from an interface
KeysOfType<Terface, Filter>
Source : KeysOfType.ts.
Will return a union of all Terface
's keys of type Filter
.
Example:
import { KeysOfType } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second: boolean;
third: string;
fourth: boolean;
}
type MyKeys = KeysOfType<MyData, boolean>;
//=> "second" | "fourth"
KeysWhereTypeCanBe<Terface, Filter>
Source : KeysWhereTypeCanBe.ts.
Returns a union of all Terface
's keys for which Filter
is assignable to the property.
Be careful: As opposed to KeysOfType<Terface, Filter>
this WILL pick nullable properties EVEN IF undefined
is not in Filter
.
Adding undefined
to Filter
will pick ALL nullable properties!
Example:
import { KeysWhereTypeCanBe } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
third: boolean;
fourth: string;
fifth: number | Date;
sixth: string | Date;
seventh?: Date;
}
type MyKeys = KeysWhereTypeCanBe<MyData, boolean | string>;
//=> "second" | "third" | "fourth" | "sixth"
// Be careful if you add undefined to Filter
type MyOtherKeys = KeysWhereTypeCanBe<MyData, boolean | string | undefined>;
//=> "second" | "third" | "fourth" | "sixth" | "seventh"
KeysNotOfType<Terface, Filter>
Source : KeysNotOfType.ts.
Will return a union of all Terface
's keys NOT of type Filter
.
Example:
import { KeysNotOfType } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second: boolean;
third: string;
fourth: boolean;
}
type MyKeys = KeysNotOfType<MyData, boolean>;
//=> "first" | "third"
KeysWhereTypeCannotBe<Terface, Filter>
Source : KeysWhereTypeCannotBe.ts.
Returns a union of all Terface
's keys for which Filter
is NOT assignable to the property.
This helper is also aliased as KeysWhereTypeCantBe<Terface, Filter>
.
Be careful: As opposed to KeysOfType<Terface, Filter>
this WILL omit nullable properties EVEN IF undefined
is not in Filter
.
Adding undefined
to Filter
will omit ALL nullable properties!
Example:
import { KeysWhereTypeCannotBe } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
third: boolean;
fourth: string;
fifth: number | Date;
sixth: string | Date;
seventh?: Date;
}
type MyKeys = KeysWhereTypeCannotBe<MyData, boolean | string>;
//=> "first" | "fifth" | "seventh"
// Be careful if you add undefined to Filter
type MyOtherKeys = KeysWhereTypeCannotBe<MyData, boolean | string | undefined>;
//=> "first" | "fifth" // Not "seventh" because it is nullable
Pick specific properties from an interface
PickMembers<Terface, K>
Source : PickMembers.ts.
Returns an interface containing the properties for which the key is specified in K
.
Example:
import { PickMembers } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
third?: string;
}
type MyNewData = PickMembers<MyData, "first" | "third">;
//=> interface MyNewData {
// first: number;
// third?: string;
// }
PickMembersOfType<Terface, Filter>
Source : PickMembersOfType.ts.
Returns an interface containing the properties for which the value is assignable to Filter
.
Be careful: this won't pick nullable properties if undefined
is not in Filter
. See PickMembersWhereTypeCanBe<Terface, Filter>
if you don't want this behavior
Example:
import { PickMembersOfType } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
third: boolean;
fourth: string;
}
type MyNewData = PickMembersOfType<MyData, boolean | string>;
//=> interface MyNewData {
// third: boolean;
// fourth: string;
// }
// Add undefined to the filter if you want to pick second
type MyOtherNewData = PickMembersOfType<MyData, boolean | string | undefined>;
//=> interface MyOtherNewData {
// second?: boolean;
// third: boolean;
// fourth: string;
// }
PickVoidMembers<Terface>
Source : PickMembersOfType.ts.
Returns an interface containing the properties for which the value is void
.
This is a shortcut for PickMembersOfType<Terface, void>
.
Example:
import { PickVoidMembers } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
third: void;
fourth: string;
}
type MyNewData = PickVoidMembers<MyData>;
//=> interface MyNewData {
// third: void;
// }
PickMembersWhereTypeCanBe<Terface, Filter>
Source : PickMembersWhereTypeCanBe.ts.
Returns an interface containing the properties for which Filter
is assignable to the property.
Be careful: As opposed to PickMembersOfType<Terface, Filter>
this WILL pick nullable properties EVEN IF undefined
is not in Filter
.
Adding undefined
to Filter
will pick ALL nullable properties!
Example:
import { PickMembersWhereTypeCanBe } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
third: boolean;
fourth: string;
fifth?: number;
}
type MyNewData = PickMembersWhereTypeCanBe<MyData, boolean | string>;
//=> interface MyNewData {
// second?: boolean; // Kept because can be boolean
// third: boolean;
// fourth: string;
// }
// Be careful if you add undefined to Filter
type MyOtherNewData = PickMembersWhereTypeCanBe<MyData, boolean | string | undefined>;
//=> interface MyOtherNewData {
// second?: boolean;
// third: boolean;
// fourth: string;
// fifth?: number; // Oops, was this expected?
// }
PickMembersNotOfType<Terface, Filter>
Source : PickMembersNotOfType.ts.
Returns an interface containing the properties for which the value is NOT assignable to Filter
.
Be careful: this WILL pick nullable properties if undefined
is not in Filter
.
Example:
import { PickMembersNotOfType } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
third: boolean;
fourth: string;
}
type MyNewData = PickMembersNotOfType<MyData, boolean | string>;
//=> interface MyNewData {
// first: number;
// second?: boolean; // Picked because undefined is not in Filter
// }
// Add undefined to the filter if you don't want to pick second
type MyOtherNewData = PickMembersNotOfType<MyData, boolean | string | undefined>;
//=> interface MyOtherNewData {
// first: number;
// }
PickNonVoidMembers<Terface>
Source : PickMembersNotOfType.ts.
Returns an interface containing the properties for which the value is NOT void
.
This is a shortcut for PickMembersNotOfType<Terface, void>
.
Example:
import { PickNonVoidMembers } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
third: void;
fourth: string;
}
type MyNewData = PickNonVoidMembers<MyData>;
//=> interface MyNewData {
// first: number;
// second?: boolean;
// fourth: string;
// }
PickMembersWhereTypeCannotBe<Terface, Filter>
Source : PickMembersWhereTypeCannotBe.ts.
Returns an interface containing the properties for which Filter
is NOT assignable to the value.
This helper is also aliased as PickMembersWhereTypeCantBe<Terface, Filter>
.
Be careful: As opposed to PickMembersNotOfType<Terface, Filter>
this WILL omit nullable properties EVEN IF undefined
is not in Filter
.
Adding undefined
to Filter
will omit ALL nullable properties!
Example:
import { PickMembersWhereTypeCannotBe } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
third: boolean;
fourth: string;
fifth: number | Date;
sixth: string | Date;
seventh?: Date;
}
type MyNewData = PickMembersWhereTypeCannotBe<MyData, boolean | string>;
//=> interface MyNewData {
// first: number;
// fifth: number | Date;
// seventh?: Date;
// }
// Be careful if you add undefined to Filter
type MyOtherNewData = PickMembersWhereTypeCannotBe<MyData, boolean | string | undefined>;
//=> interface MyOtherNewData {
// first: number;
// fifth: number | Date;
// // seventh is omitted because it is nullable
// }
Modify an interface
ReplaceType<Terface, Filter, New>
Source : ReplaceType.ts.
Returns an interface where all properties assignable to Filter
are now of type New
.
Be careful: this won't replace nullable properties if undefined
is not in Filter
.
Example:
import { ReplaceType } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
third: boolean;
fourth: string;
}
type MyNewData = ReplaceType<MyData, boolean | string, number>;
//=> interface MyNewData {
// first: number;
// second?: boolean; // Not replaced : undefined is not in Filter
// third: number;
// fourth: number;
// }
type MyOtherNewData = ReplaceType<MyData, boolean | string | undefined, number>;
//=> interface MyOtherNewData {
// first: number;
// second: number; // Replaced BUT NOT NULLABLE ANYMORE!
// third: number;
// fourth: number;
// }
ReplaceTypeIfCanBe<Terface, Filter, New>
Source : ReplaceType.ts.
Returns an interface where all properties P
for which Filter
is assignable to P
are now of type New
.
Be careful: this will replace ALL nullable properties if undefined
is in Filter
.
Be careful: this is a strict replacement. Adding boolean
to Filter
will match boolean | number
and replace it with New
, not with New | number
.
Example:
import { ReplaceTypeIfCanBe } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
third: boolean;
fourth: string;
fifth: number | Date;
sixth: string | Date;
seventh?: Date;
}
type MyNewData = ReplaceTypeIfCanBe<MyData, boolean | string, number>;
//=> interface MyNewData {
// first: number;
// second: number; // Strictly replaced : not nullable anymore
// third: number;
// fourth: number;
// fifth: number | Date;
// sixth: number; // Strictly replaced : Can't be Date anymore
// seventh?: Date;
// }
// Adding undefined to the filter is dangerous: it will replace all nullable properties
type MyOtherNewData = ReplaceTypeIfCanBe<MyData, boolean | string | undefined, number>;
//=> interface MyOtherNewData {
// first: number;
// second: number;
// third: number;
// fourth: number;
// fifth: number | Date;
// sixth: number;
// seventh: number; // Oops! Didn't expect this one
// }
MakeNonOptional<Terface, K>
Source : MakeNonOptional.ts.
Will return an interface where all properties in the union K
are required. All properties not in the union K
are left as is.
This helper will not recurse at all!
Example:
import { MakeNonOptional } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
third?: string;
deep?: {
key: number;
key2?: string;
};
}
type MyNewData = MakeNonOptional<MyData, "second" | "deep">;
//=> interface MyNewData {
// first: number;
// second: boolean; // Required
// third?: string; // Untouched : Not in K
// deep: { // Required
// key: number;
// key2?: string; // Untouched : No recursion
// };
// }
MakeDeepNonOptional<Terface, K>
Source : MakeNonOptional.ts.
Will return an interface where all properties in the union K
are required. All properties not in the union K
are left as is.
If one of the properties specified in K
is an interface, all its properties will recursively be marked as required as well.
This helper will recurse and mark everything down as required!
Example:
import { MakeDeepNonOptional } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
third?: string;
deep?: {
key: number;
key2?: string;
deepAgain?: {
alpha: string;
beta?: string;
};
};
}
type MyNewData = MakeDeepNonOptional<MyData, "second" | "deep">;
//=> interface MyNewData {
// first: number;
// second: boolean; // Required
// third?: string; // Untouched : Not in K
// deep: { // Required
// key: number;
// key2: string; // Required by recursion
// deepAgain: { // Required by recursion
// alpha: string;
// beta: string; // Required by recursion
// };
// };
// }
Types
Scalar
Source : Scalar.ts.
Shortcut for string | number | boolean
.
NullableScalar
Source : Scalar.ts.
Shortcut for Scalar | null
.
OptionalScalar
Source : Scalar.ts.
Shortcut for Scalar | undefined
.
OptionalNullableScalar
Source : Scalar.ts.
Shortcut for NullableScalar | undefined
.
ObjectOf<T>
Source : ObjectOf.ts.
Shortcut for creating Record
s of type Record<string, T>
.
Example:
import { ObjectOf } from "@telokys/ts-meta-types";
// Equivalent to Record<string, boolean>
type MyObject = ObjectOf<boolean>;
//=> {
// [key: string]: boolean;
// }
ValueOf<Terface>
Source : ValueOf.ts.
Returns a union containing the types of all values of Terface
.
Example:
import { ValueOf } from "@telokys/ts-meta-types";
interface MyData {
first: number;
second?: boolean;
duplicate: boolean;
third?: string;
deep?: {
key: number;
key2?: string;
deepAgain?: {
alpha: string;
beta?: string;
};
};
}
type MyNewData = ValueOf<MyData>;
//=> string
// | number
// | boolean
// | {
// key: number;
// key2?: string;
// deepAgain?: {
// alpha: string;
// beta?: string;
// };
// }
// | undefined
Misc
Debug<Terface>
Source : Debug.ts.
Taken from https://stackoverflow.com/a/57683652/4613742.
Will "clean" an interface in order for the intellisense to properly display the real computed type.
Be careful: This is not recursive.
Example:
Given the following code
import { Debug, MakeNonOptional, MakeDeepNonOptional } from "@telokys/ts-meta-types";
interface Test {
test: boolean;
test2?: number;
test3: number;
deep?: {
tmp: string;
tmp2?: string;
}
}
type RawNonOptional = MakeNonOptional<Test>;
type RawNonOptionalDeep = MakeDeepNonOptional<Test>;
type DebuggedNonOptional = Debug<RawNonOptional>;
type DebuggedNonOptionalDeep = Debug<RawNonOptionalDeep>;
Here the intellisense given by VSCode for the first two types:
As you can see, there are Required<>
in someplaces. We have to mentally interpret them.
Do Required
apply recursively? I don't want to remember, I want the intellisense to tell me the real type.
Wrapping the type in Debug
will display the following:
Now the intellisense is much more helpful. I can instantly see the updated version is doing what I hoped it would.
Note that the
Debug
helper is not recursive, as seen on the right image. If you want the recursive version, seeDebugR<Terface>
DebugR<Terface>
Source : Debug.ts.
Taken from https://stackoverflow.com/a/57683652/4613742.
Will recursively "clean" an interface in order for the intellisense to properly display the real computed type.
Example:
Given the following code
import { DebugR, MakeNonOptional, MakeDeepNonOptional } from "@telokys/ts-meta-types";
interface Test {
test: boolean;
test2?: number;
test3: number;
deep?: {
tmp: string;
tmp2?: string;
}
}
type RawNonOptional = MakeNonOptional<Test>;
type RawNonOptionalDeep = MakeDeepNonOptional<Test>;
type RecursivelyDebuggedNonOptional = DebugR<RawNonOptional>;
type RecursivelyDebuggedNonOptionalDeep = DebugR<RawNonOptionalDeep>;
Here the intellisense given by VSCode for the first two types:
As you can see, there are Required<>
in someplaces. We have to mentally interpret them.
Do Required
apply recursively? I don't want to remember, I want the intellisense to tell me the real type.
Wrapping the type in DebugR
will display the following:
Now the intellisense is much more helpful. I can instantly see the updated version is doing what I hoped it would.