mirror of
https://github.com/yume-chan/ya-webadb.git
synced 2025-10-03 01:39:21 +02:00
97 lines
2.8 KiB
TypeScript
97 lines
2.8 KiB
TypeScript
/**
|
|
* When evaluating a very complex generic type alias,
|
|
* tell TypeScript to use `T`, instead of current type alias' name, as the result type name
|
|
*
|
|
* Example:
|
|
*
|
|
* ```ts
|
|
* type WithIdentity<T> = Identity<SomeType<T>>;
|
|
* type WithoutIdentity<T> = SomeType<T>;
|
|
*
|
|
* type WithIdentityResult = WithIdentity<number>;
|
|
* // Hover on this one shows `SomeType<number>`
|
|
*
|
|
* type WithoutIdentityResult = WithoutIdentity<number>;
|
|
* // Hover on this one shows `WithoutIdentity<number>`
|
|
* ```
|
|
*/
|
|
export type Identity<T> = T;
|
|
|
|
/**
|
|
* Collapse an intersection type (`{ foo: string } & { bar: number }`) to a simple type (`{ foo: string, bar: number }`)
|
|
*/
|
|
export type Evaluate<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;
|
|
|
|
/**
|
|
* Overwrite fields in `TBase` with fields in `TNew`
|
|
*/
|
|
export type Overwrite<TBase extends object, TNew extends object> = Evaluate<
|
|
Omit<TBase, keyof TNew> & TNew
|
|
>;
|
|
|
|
/**
|
|
* Remove fields with `never` type
|
|
*/
|
|
export type OmitNever<T> = Pick<
|
|
T,
|
|
{ [K in keyof T]: [T[K]] extends [never] ? never : K }[keyof T]
|
|
>;
|
|
|
|
/**
|
|
* Extract keys of fields in `T` that has type `TValue`
|
|
*/
|
|
export type KeysOfType<T, TValue> = {
|
|
[TKey in keyof T]: T[TKey] extends TValue ? TKey : never;
|
|
}[keyof T];
|
|
|
|
export type ValueOrPromise<T> = T | PromiseLike<T>;
|
|
|
|
/**
|
|
* Returns a (fake) value of the given type.
|
|
*/
|
|
export function placeholder<T>(): T {
|
|
return undefined as unknown as T;
|
|
}
|
|
|
|
// This library can't use `@types/node` or `lib: dom`
|
|
// because they will pollute the global scope
|
|
// So `TextEncoder` and `TextDecoder` types are not available
|
|
|
|
// Node.js 8.3 ships `TextEncoder` and `TextDecoder` in `util` module.
|
|
// But using top level await to load them requires Node.js 14.1.
|
|
// So there is no point to do that. Let's just assume they exist in global.
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
declare class TextEncoderType {
|
|
constructor();
|
|
|
|
encode(input: string): Uint8Array;
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
declare class TextDecoderType {
|
|
constructor();
|
|
|
|
decode(buffer: ArrayBufferView | ArrayBuffer): string;
|
|
}
|
|
|
|
interface GlobalExtension {
|
|
TextEncoder: typeof TextEncoderType;
|
|
TextDecoder: typeof TextDecoderType;
|
|
}
|
|
|
|
const { TextEncoder, TextDecoder } = globalThis as unknown as GlobalExtension;
|
|
|
|
const SharedEncoder = /* #__PURE__ */ new TextEncoder();
|
|
const SharedDecoder = /* #__PURE__ */ new TextDecoder();
|
|
|
|
/* #__NO_SIDE_EFFECTS__ */
|
|
export function encodeUtf8(input: string): Uint8Array {
|
|
return SharedEncoder.encode(input);
|
|
}
|
|
|
|
export function decodeUtf8(buffer: ArrayBufferView | ArrayBuffer): string {
|
|
// `TextDecoder` has internal states in stream mode,
|
|
// but this method is not for stream mode, so the instance can be reused
|
|
return SharedDecoder.decode(buffer);
|
|
}
|