Gazebo_simulation-Frontend/node_modules/ts-essentials/README.md
2020-12-21 10:29:31 -05:00

597 lines
21 KiB
Markdown

<p align="center">
<img src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/240/google/146/toolbox_1f9f0.png" width="120" alt="ts-essentials">
<h3 align="center">ts-essentials</h3>
<p align="center">All essential TypeScript types in one place 🤙</p>
<p align="center">
<img alt="Downloads" src="https://img.shields.io/npm/dm/ts-essentials.svg">
<img alt="Build status" src="https://circleci.com/gh/krzkaczor/ts-essentials.svg?style=svg">
<a href="/package.json"><img alt="Software License" src="https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square"></a>
<img src="https://img.shields.io/badge/all_contributors-15-orange.svg?style=flat-square" alt="All Contributors">
<a href="https://codechecks.io"><img src="https://raw.githubusercontent.com/codechecks/docs/master/images/badges/badge-default.svg?sanitize=true" alt="codechecks.io"></a>
</p>
</p>
## Install
```sh
npm install --save-dev ts-essentials
```
👉 We require `typescript>=3.5`. If you're looking for support for older TS versions use `ts-essentials@2` instead.
## What's inside?
- [Install](#Install)
- [What's inside?](#Whats-inside)
- [Basic](#Basic)
- [Dictionaries](#Dictionaries)
- [Deep Partial & Deep Required & Deep Readonly & Deep NonNullable](#Deep-Partial--Deep-Required--Deep-Readonly--Deep-NonNullable)
- [Writable](#Writable)
- [Buildable](#Buildable)
- [Omit](#Omit)
- [StrictOmit](#StrictOmit)
- [Comparison between `Omit` and `StrictOmit`](#Comparison-between-Omit-and-StrictOmit)
- [DeepOmit](#DeepOmit)
- [OmitProperties](#OmitProperties)
- [PickProperties](#PickProperties)
- [NonNever](#NonNever)
- [Merge](#Merge)
- [MarkRequired](#MarkRequired)
- [MarkOptional](#MarkOptional)
- [ReadonlyKeys](#ReadonlyKeys)
- [WritableKeys](#WritableKeys)
- [UnionToIntersection](#UnionToIntersection)
- [Opaque types](#Opaque-types)
- [Tuple constraint](#Tuple-constraint)
- [Literal types](#Literal-types)
- [Exhaustive switch cases](#Exhaustive-switch-cases)
- [ValueOf type](#ValueOf-type)
- [AsyncOrSync type](#AsyncOrSync-type)
- [Contributors](#Contributors)
### Basic
- `Primitive` type matching all primitive values.
### Dictionaries
```typescript
const stringDict: Dictionary<string> = {
a: "A",
b: "B",
};
// Specify second type argument to change dictionary keys type
const dictOfNumbers: Dictionary<string, number> = {
420: "four twenty",
1337: "HAX",
};
// You may specify union types as key to cover all possible cases. It acts the same as Record from TS's standard library
export type DummyOptions = "open" | "closed" | "unknown";
const dictFromUnionType: Dictionary<number, DummyOptions> = {
closed: 1,
open: 2,
unknown: 3,
};
// and get dictionary values
type stringDictValues = DictionaryValues<typeof stringDict>;
// Result: string
```
### Deep Partial & Deep Required & Deep Readonly & Deep NonNullable
```typescript
type ComplexObject = {
simple: number;
nested: {
a: string;
array: [{ bar: number }];
};
};
type ComplexObjectPartial = DeepPartial<ComplexObject>;
const samplePartial: ComplexObjectPartial = {
nested: {
array: [{}],
},
};
type ComplexObjectAgain = DeepRequired<ComplexObjectPartial>;
const sampleRequired: ComplexObjectAgain = {
simple: 5,
nested: {
a: "test",
array: [{bar: 1}],
},
};
type ComplexObjectReadonly = DeepReadonly<ComplexObject>;
type ComplexNullableObject = {
simple: number | null | undefined;
nested: {
a: string | null | undefined;
array: [{ bar: number | null | undefined }] | null | undefined;
};
};
type ComplexObjectNonNullable = DeepNonNullable<ComplexNullableObject>;
const sampleNonNullable: ComplexObjectNonNullable = {
simple: 5,
nested: {
a: "test",
array: [{bar: null}], // Error: Type 'null' is not assignable to type 'number'
}
}
```
### Writable
Make all attributes of object writable.
```typescript
type Foo = {
readonly a: number;
readonly b: string;
};
const foo: Foo = ({ a: 1, b: "b" }(foo as Writable<typeof foo>).a = 42);
```
```typescript
type Foo = {
readonly foo: string;
bar: {
readonly x: number;
};
}[];
const test: DeepWritable<Foo> = [
{
foo: "a",
bar: {
x: 5,
},
},
];
// we can freely write to this object
test[0].foo = "b";
test[0].bar.x = 2;
```
### Buildable
A combination of both `DeepWritable` and `DeepPartial`.
This type allows building an object step-by-step by assigning values to its attributes in multiple statements.
```typescript
interface ReadonlyObject extends Readonly<{
simple: number;
nested: Readonly<{
a: string;
array: ReadonlyArray<Readonly<{ bar: number }>>;
}>;
}> {}
const buildable: Buildable<ReadonlyObject> = {};
buildable.simple = 7;
buildable.nested = {};
buildable.nested.a = 'test';
buildable.nested.array = [];
buildable.nested.array.push({ bar: 1 });
const finished = buildable as ReadonlyObject;
```
### Omit
Our version of `Omit` is renamed to `StrictOmit` in `v3`, since the builtin `Omit` has become part of TypeScript 3.5
### StrictOmit
Usage is similar to the builtin version, but checks the filter type more strictly.
```typescript
type ComplexObject = {
simple: number;
nested: {
a: string;
array: [{ bar: number }];
};
};
type SimplifiedComplexObject = StrictOmit<ComplexObject, "nested">;
// Result:
// {
// simple: number
// }
// if you want to Omit multiple properties just use union type:
type SimplifiedComplexObject = StrictOmit<ComplexObject, "nested" | "simple">;
// Result:
// { } (empty type)
```
#### Comparison between `Omit` and `StrictOmit`
Following the code above, we can compare the behavior of `Omit` and `StrictOmit`.
```typescript
type SimplifiedComplexObjectWithStrictOmit = StrictOmit<ComplexObject, "nested" | "simple" | "nonexistent">;
// Result: error
// Type '"simple" | "nested" | "nonexistent"' does not satisfy the constraint '"simple" | "nested"'.
// Type '"nonexistent"' is not assignable to type '"simple" | "nested"'.
type SimplifiedComplexObjectWithOmit = Omit<ComplexObject, "nested" | "simple" | "nonexistent">;
// Result: no error
```
As is shown in the example, `StrictOmit` ensures that no extra key is specified in the filter.
### DeepOmit
Recursively omit deep properties according to key names.
Here is the `Teacher` interface.
```typescript
interface Teacher {
name: string,
gender: string,
students: {name: string, score: number}[]
}
```
Now suppose you want to omit `gender` property of `Teacher`, and `score` property of `students`. You can achieve this with a simple type filter.
In the filter, the properties to be omitted completely should be defined as `never`. For the properties you want to partially omit, you should recursively define the sub-properties to be omitted.
```typescript
type TeacherSimple = DeepOmit<Teacher, {
gender: never,
students: {
score: never,
}
}>
// The result will be:
// {
// name: string,
// students: {name: string}[]
// }
```
NOTE
- `DeepOmit` works fine with `Array`s and `Set`s. When applied to a `Map`, the filter is only applied to its value.
- If there exists any property in the filter which is not in the original type, an error will occur.
### OmitProperties
Removes all properties extending type `P` in type `T`.
```typescript
interface Example {
log(): void;
version: string;
}
type ExampleWithoutMethods = OmitProperties<Example, Function>;
// Result:
// {
// version: string;
// }
// if you want to Omit multiple properties just use union type like
type ExampleWithoutMethods = OmitProperties<Example, Function | string>;
// Result:
// { } (empty type)
```
### PickProperties
Pick only properties extending type `P` in type `T`.
```typescript
interface Example {
log(): void;
version: string;
versionNumber: number;
}
type ExampleOnlyMethods = PickProperties<Example, Function>;
// Result:
// {
// log(): void;
// }
// if you want to pick multiple properties just use union type like
type ExampleOnlyMethodsAndString = PickProperties<Example, Function | string>;
// Result:
// {
// log(): void;
// version: string;
// }
```
### NonNever
Useful for purifying object types. It improves intellisense but also allows for extracting keys satisfying a conditional
type.
```typescript
type GetDefined<TypesMap extends { [key: string]: any }> = keyof NonNever<
{ [T in keyof TypesMap]: TypesMap[T] extends undefined ? never : TypesMap[T] }
>;
```
### NonEmptyObject
Useful for accepting only objects with keys, great after a filter like OmitProperties or PickProperties.
```typescript
/* return never if the object doesn't have any number value*/
type NumberDictionary<T> = NonEmptyObject<PickProperties<T, number>>;
// return { a: number }
type SomeObject = NumberDictionary<{ a: number, b: string }>;
// return never
type EmptyObject = NumberDictionary<{}>;
```
### Merge
```typescript
type Foo = {
a: number;
b: string;
};
type Bar = {
b: number;
};
const xyz: Merge<Foo, Bar> = { a: 4, b: 2 };
// Result:
// {
// a: number,
// b: number,
// }
```
### MarkRequired
Useful when you're sure some optional properties will be set. A real life example: when selecting
an object with its related entities from an ORM.
```typescript
class User {
id: number;
posts?: Post[];
photos?: Photo[];
}
type UserWithPosts = MarkRequired<User, 'posts'>;
// example usage with a TypeORM repository -- `posts` are now required, `photos` are still optional
async function getUserWithPosts(id: number): Promise<UserWithPosts> {
return userRepo.findOneOrFail({ id }, { relations: ['posts'] }) as Promise<UserWithPosts>;
}
```
### MarkOptional
Useful when you want to make some properties optional without creating a separate type.
```typescript
interface User {
id: number;
name: string;
email: string;
password: string;
}
type UserWithoutPassword = MarkOptional<User, 'password'>;
// Result:
// {
// id: number;
// name: string;
// email: string;
// password?: string;
// }
```
### ReadonlyKeys
Gets keys of an object which are readonly.
```typescript
type T = {
readonly a: number;
b: string;
};
type Result = ReadonlyKeys<T>
// Result:
// "a"
```
### WritableKeys
Gets keys of an object which are writable.
```typescript
type T = {
readonly a: number;
b: string;
};
type Result = WritableKeys<T>
// Result:
// "b"
```
### UnionToIntersection
Useful for converting mapped types with function values to intersection type (so in this case - overloaded function).
```typescript
type Foo = {
bar: string;
xyz: number;
};
type Fn = UnionToIntersection<{ [K in keyof Foo]: (type: K, arg: Foo[K]) => any }[keyof Foo]>;
```
### Opaque types
```typescript
type PositiveNumber = Opaque<number, "positive-number">;
function makePositiveNumber(n: number): PositiveNumber {
if (n <= 0) {
throw new Error("Value not positive !!!");
}
return (n as any) as PositiveNumber; // this ugly cast is required but only when "producing" opaque types
}
```
### Tuple constraint
```typescript
function foo<T extends Tuple>(tuple: T): T {
return tuple;
}
const ret = foo(["s", 1]);
// return type of [string, number]
```
You can also parametrize `Tuple` type with a type argument to constraint it to certain types, i.e.
`Tuple<string | number>`.
### Literal types
_For TypeScript >= 3.4_: TypeScript 3.4 shipped
[`const` assertions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) which are very
similar to our `literal` helper but also make type readonly, you should prefer `as const` construct.
`literal` is deprecated tn `ts-essentials` 3.x, which requires TypeScript >=3.5.
_For TypeScript < 3.4_: this is served as a backport of the [`const` assertions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) added since TypeScript 3.4.
```typescript
// prevent type widening https://blog.mariusschulz.com/2017/02/04/typescript-2-1-literal-type-widening
const t = {
letter: literal("a"), // type stays "a" not string
digit: literal(5), // type stays 5 not number
};
```
### Exhaustive switch cases
```typescript
function actOnDummyOptions(options: DummyOptions): string {
switch (options) {
case "open":
return "it's open!";
case "closed":
return "it's closed";
case "unknown":
return "i have no idea";
default:
// if you would add another option to DummyOptions, you'll get error here!
throw new UnreachableCaseError(options);
}
}
```
### ValueOf type
```typescript
const obj = {
id: "123e4567-e89b-12d3-a456-426655440000",
name: "Test object",
timestamp: 1548768231486,
};
type objKeys = ValueOf<typeof obj>;
// Result: string | number
```
### AsyncOrSync type
Useful as a return type in interfaces or abstract classes with missing implementation
```typescript
interface CiProvider {
getSHA(): AsyncOrSync<string>;
// same as
getSHA(): Promise<string> | string;
}
class Circle implements CiProvider {
// implementation can use sync version
getSHA() {
return "abc";
}
}
class Travis implements CiProvider {
// implementation can use async version when needed
async getSHA() {
// do async call
return "def";
}
}
```
## Contributors
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore -->
<table>
<tr>
<td align="center"><a href="https://twitter.com/krzkaczor"><img src="https://avatars2.githubusercontent.com/u/1814312?v=4" width="100px;" alt="Chris Kaczor"/><br /><sub><b>Chris Kaczor</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=krzkaczor" title="Code">💻</a> <a href="#business-krzkaczor" title="Business development">💼</a> <a href="#example-krzkaczor" title="Examples">💡</a> <a href="https://github.com/krzkaczor/ts-essentials/commits?author=krzkaczor" title="Documentation">📖</a></td>
<td align="center"><a href="https://scholar.google.com/citations?user=3xZtvpAAAAAJ"><img src="https://avatars3.githubusercontent.com/u/9780746?v=4" width="100px;" alt="Xiao Liang"/><br /><sub><b>Xiao Liang</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=yxliang01" title="Code">💻</a> <a href="#ideas-yxliang01" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/krzkaczor/ts-essentials/commits?author=yxliang01" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/Andarist"><img src="https://avatars2.githubusercontent.com/u/9800850?v=4" width="100px;" alt="Mateusz Burzyński"/><br /><sub><b>Mateusz Burzyński</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=Andarist" title="Code">💻</a> <a href="#ideas-Andarist" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/krzkaczor/ts-essentials/commits?author=Andarist" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/macbem"><img src="https://avatars1.githubusercontent.com/u/12464061?v=4" width="100px;" alt="Maciej Bembenista"/><br /><sub><b>Maciej Bembenista</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=macbem" title="Code">💻</a> <a href="#ideas-macbem" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/krzkaczor/ts-essentials/commits?author=macbem" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/MichaelTontchev"><img src="https://avatars0.githubusercontent.com/u/12261336?v=4" width="100px;" alt="Michael Tontchev"/><br /><sub><b>Michael Tontchev</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=MichaelTontchev" title="Code">💻</a> <a href="#ideas-MichaelTontchev" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/krzkaczor/ts-essentials/commits?author=MichaelTontchev" title="Documentation">📖</a></td>
<td align="center"><a href="http://ThomasdH.blogspot.com"><img src="https://avatars0.githubusercontent.com/u/3889750?v=4" width="100px;" alt="Thomas den Hollander"/><br /><sub><b>Thomas den Hollander</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=ThomasdenH" title="Code">💻</a> <a href="#ideas-ThomasdenH" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/krzkaczor/ts-essentials/commits?author=ThomasdenH" title="Documentation">📖</a></td>
<td align="center"><a href="https://twitter.com/esamatti"><img src="https://avatars3.githubusercontent.com/u/225712?v=4" width="100px;" alt="Esa-Matti Suuronen"/><br /><sub><b>Esa-Matti Suuronen</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=epeli" title="Code">💻</a> <a href="#ideas-epeli" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/krzkaczor/ts-essentials/commits?author=epeli" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/IlyaSemenov"><img src="https://avatars1.githubusercontent.com/u/128121?v=4" width="100px;" alt="Ilya Semenov"/><br /><sub><b>Ilya Semenov</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=IlyaSemenov" title="Code">💻</a> <a href="#ideas-IlyaSemenov" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/krzkaczor/ts-essentials/commits?author=IlyaSemenov" title="Documentation">📖</a></td>
<td align="center"><a href="https://codechecks.io"><img src="https://avatars2.githubusercontent.com/u/46399828?v=4" width="100px;" alt="Code Checks"/><br /><sub><b>Code Checks</b></sub></a><br /><a href="#review-codechecks" title="Reviewed Pull Requests">👀</a></td>
<td align="center"><a href="http://www.nomiclabs.io"><img src="https://avatars1.githubusercontent.com/u/176499?v=4" width="100px;" alt="Patricio Palladino"/><br /><sub><b>Patricio Palladino</b></sub></a><br /><a href="#ideas-alcuadrado" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="http://twitter.com/quezak2"><img src="https://avatars0.githubusercontent.com/u/666206?v=4" width="100px;" alt="Artur Kozak"/><br /><sub><b>Artur Kozak</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=quezak" title="Code">💻</a> <a href="#ideas-quezak" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/krzkaczor/ts-essentials/commits?author=quezak" title="Documentation">📖</a> <a href="#review-quezak" title="Reviewed Pull Requests">👀</a></td>
<td align="center"><a href="https://github.com/lucifer1004"><img src="https://avatars2.githubusercontent.com/u/13583761?v=4" width="100px;" alt="Zihua Wu"/><br /><sub><b>Zihua Wu</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=lucifer1004" title="Code">💻</a> <a href="#ideas-lucifer1004" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/krzkaczor/ts-essentials/commits?author=lucifer1004" title="Documentation">📖</a></td>
<td align="center"><a href="http://kevinpeno.com"><img src="https://avatars1.githubusercontent.com/u/343808?v=4" width="100px;" alt="Kevin Peno"/><br /><sub><b>Kevin Peno</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=kevinpeno" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/DomParfitt"><img src="https://avatars2.githubusercontent.com/u/11363907?v=4" width="100px;" alt="Dom Parfitt"/><br /><sub><b>Dom Parfitt</b></sub></a><br /><a href="#ideas-DomParfitt" title="Ideas, Planning, & Feedback">🤔</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/EduardoRFS"><img src="https://avatars0.githubusercontent.com/u/3393115?v=4" width="100px;" alt="EduardoRFS"/><br /><sub><b>EduardoRFS</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=EduardoRFS" title="Code">💻</a> <a href="https://github.com/krzkaczor/ts-essentials/commits?author=EduardoRFS" title="Documentation">📖</a></td>
<td align="center"><a href="https://andydvorak.net/"><img src="https://avatars1.githubusercontent.com/u/409245?v=4" width="100px;" alt="Andrew C. Dvorak"/><br /><sub><b>Andrew C. Dvorak</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=acdvorak" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/a1russell"><img src="https://avatars0.githubusercontent.com/u/241628?v=4" width="100px;" alt="Adam Russell"/><br /><sub><b>Adam Russell</b></sub></a><br /><a href="https://github.com/krzkaczor/ts-essentials/commits?author=a1russell" title="Code">💻</a> <a href="https://github.com/krzkaczor/ts-essentials/commits?author=a1russell" title="Documentation">📖</a></td>
</tr>
</table>
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! [Read more](./CONTRIBUTING.md)