TypeScript
TS 相关
standard-schema ---> TS Validate 标准接口
由如下 TS 定义组成:
standard-schema
/** The Standard Schema interface. */
export interface StandardSchemaV1<Input = unknown, Output = Input> {
/** The Standard Schema properties. */
readonly '~standard': StandardSchemaV1.Props<Input, Output>;
}
export declare namespace StandardSchemaV1 {
/** The Standard Schema properties interface. */
export interface Props<Input = unknown, Output = Input> {
/** The version number of the standard. */
readonly version: 1;
/** The vendor name of the schema library. */
readonly vendor: string;
/** Validates unknown input values. */
readonly validate: (
value: unknown
) => Result<Output> | Promise<Result<Output>>;
/** Inferred types associated with the schema. */
readonly types?: Types<Input, Output> | undefined;
}
/** The result interface of the validate function. */
export type Result<Output> = SuccessResult<Output> | FailureResult;
/** The result interface if validation succeeds. */
export interface SuccessResult<Output> {
/** The typed output value. */
readonly value: Output;
/** The non-existent issues. */
readonly issues?: undefined;
}
/** The result interface if validation fails. */
export interface FailureResult {
/** The issues of failed validation. */
readonly issues: ReadonlyArray<Issue>;
}
/** The issue interface of the failure output. */
export interface Issue {
/** The error message of the issue. */
readonly message: string;
/** The path of the issue, if any. */
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
}
/** The path segment interface of the issue. */
export interface PathSegment {
/** The key representing a path segment. */
readonly key: PropertyKey;
}
/** The Standard Schema types interface. */
export interface Types<Input = unknown, Output = Input> {
/** The input type of the schema. */
readonly input: Input;
/** The output type of the schema. */
readonly output: Output;
}
/** Infers the input type of a Standard Schema. */
export type InferInput<Schema extends StandardSchemaV1> = NonNullable<
Schema['~standard']['types']
>['input'];
/** Infers the output type of a Standard Schema. */
export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<
Schema['~standard']['types']
>['output'];
}effect ---> 构建健壮的 TS 应用
Effect 由多个包组成,这些包协同工作以帮助构建健壮的 TypeScript 应用程序。核心包 effect 充当框架的基础,提供用于管理副作用、确保类型安全和支持并发的基元。
import { Effect } from "effect"
// type Effect<Success, Error, Requirements> = (
// context: Context<Requirements>
// ) => Error | Success
const divide = (a: number, b: number): Effect.Effect<number, Error> =>
b === 0
? Effect.fail(new Error("Cannot divide by zero"))
: Effect.succeed(a / b)tsd ---> TS 类型运行时验证库
虽然 vitest 等库也有类似的功能,但是当仅仅想验证 TS 类型的作为测试的时候,可以使用这个库
$ [npx] tsd [path]测试文件使用 *.test-d.ts 结尾
import {expectType} from 'tsd';
import concat from '.';
expectType<string>(concat('foo', 'bar'));
expectType<string>(concat(1, 2));xterm ---> 终端组件
如果想在 Web 页面中实现一个终端,xterm 绝对是一个不错的选择
import { Terminal } from 'xterm';
const terminal = new Terminal();
terminal.open(document.getElementById('terminal'));
terminal.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ')ts-essentials ---> 常用的 TS 泛型库
包含了常用的泛型类型方法:
- 基本的,例如:Builtin、Primitive、Writable
<Type>等 - 深层包装器类型,例如:DeepOmit
<Type, Filter>、DeepPick<Type, Filter>等 - Key 类型,例如:PickKeys<Type, Value>、RequiredKeys
<Type>等 - 类型检查器,例如:IsAny
<Type>、IsTuple<Type>等 - 数组和元组,例如:Head
<Type>、ReadonlyArrayOrSingle 等 - ...
memoize ---> 缓存函数结果
适用于包裹某些耗时的,并且当参数相同时,返回值相同的函数,避免重复计算
import memoize from 'memoize';
let index = 0;
const counter = () => ++index;
const memoized = memoize(counter);
memoized('foo');
//=> 1
// Cached as it's the same argument
memoized('foo');
//=> 1也有异步函数的版本 sindresorhus/p-memoize
typedoc ---> ts类型文档生成器
为你的导出的ts类型生成文档
$ npm install typedoc
$ typedoc src/index.tstypescript-json ---> JSON快速序列化和类型检查
import TSON from "typescript-json";
// RUNTIME TYPE CHECKERS
TSON.assertType<T>(input); // throws exception
TSON.is<T>(input); // returns boolean value
TSON.validate<T>(input); // archives all type errors
// STRINGIFY
TSON.stringify<T>(input); // 5x faster JSON.stringify()
// APPENDIX FUNCTIONS
TSON.application<[T, U, V], "swagger">(); // JSON schema application generator
TSON.create<T>(input); // 2x faster object creator (only one-time construction)type-fest ---> ts 类型库
import type {Except} from 'type-fest';
type Foo = {
unicorn: string;
rainbow: boolean;
};
type FooWithoutRainbow = Except<Foo, 'rainbow'>;
//=> {unicorn: string}joi ---> 精确地描述数据与预期的差异
通过配置标准数据的预定格式,给出与测试数据不一致的描述
import Joi from 'joi'
const schema = Joi.object({
username: Joi.string().alphanum().min(3).max(30).required(),
password: Joi.string().pattern(new RegExp('^[a-zA-Z0-9]{3,30}$')),
repeat_password: Joi.ref('password'),
access_token: [ Joi.string(), Joi.number()],
birth_year: Joi.number().integer().min(1900).max(2013),
email: Joi.string().email({ minDomainSegments: 2, tlds: { allow: ['com', 'net'] } })
}).with('username', 'birth_year')
.xor('password', 'access_token')
.with('password', 'repeat_password');
console.log(schema.validate({ username: 'abc', birth_year: 1994 }))
/*
{
value: { username: 'abc', birth_year: 1994 },
error: [Error [ValidationError]: "value" must contain at least one of [password, access_token]] {
_original: { username: 'abc', birth_year: 1994 },
details: [ [Object] ]
}
}
*/其他类似的库
| Library | Minified size | Gzipped size | Compression rate | Stars |
|---|---|---|---|---|
| Superstruct | 11.5 kB | 3.4 kB | 70.43 % | |
| io-ts | 20.5 kB | 5.2 kB | 74.63 % | |
| Runtypes | 30.6 kB | 7.4 kB | 75.82 % | |
| Valibot | 46.7 kB | 7.5 kB | 83.94 % | |
| Yup | 40.08 kB | 12.4 kB | 69.06 % | |
| Zod | 57 kB | 13.2 kB | 76.84 % | |
| Ajv | 119.6 kB | 35.2 kB | 70.57 % | |
| Joi | 151.1 kB | 43 kB | 71.54 % |
trpc ---> 配合zod,提供端到端类型安全的API
$ npm install @trpc/server @trpc/clientimportx ---> 在 NodeJs 运行时导入 Typescript 的统一工具
有很多方法可以做到在 JS 中导入 TS, importx 可以自动选择最合适的 loader 来导入,以便提供最合适的方式和最好的性能
const mod = await import('importx').then(x => x.import('./path/to/module.ts', import.meta.url))内部集成的 loader:
import { tsImport } from 'tsx/esm/api'
const loaded = await tsImport('./file.ts', import.meta.url)const jiti = require("jiti")(__filename);
jiti("./path/to/file.ts");import { bundleRequire } from 'bundle-require'
const { mod } = await bundleRequire({
filepath: './project/vite.config.ts',
})Auto 模式下的识别流程图:
yup ---> 将类型检验带到运行时
import { object, string, number, date, InferType } from 'yup';
let userSchema = object({
name: string().required(),
age: number().required().positive().integer(),
email: string().email(),
website: string().url().nullable(),
createdOn: date().default(() => new Date()),
});
// parse and assert validity
const user = await userSchema.validate(await fetchUser());
type User = InferType<typeof userSchema>;
/* {
name: string;
age: number;
email?: string | undefined
website?: string | null | undefined
createdOn: Date
}*/ts-pattern ---> TS 安全的条件匹配
import { match, P } from 'ts-pattern';
type Data =
| { type: 'text'; content: string }
| { type: 'img'; src: string };
type Result =
| { type: 'ok'; data: Data }
| { type: 'error'; error: Error };
const result: Result = ...;
const html = match(result)
.with({ type: 'error' }, () => <p>Oups! An error occured</p>)
.with({ type: 'ok', data: { type: 'text' } }, (res) => <p>{res.data.content}</p>)
.with({ type: 'ok', data: { type: 'img', src: P.select() } }, (src) => <img src={src} />)
.exhaustive();untyped ---> 根据对象生成类型或MD
const defaultPlanet = {
name: "earth",
specs: {
gravity: {
$resolve: (val) => parseFloat(val),
$default: "9.8",
},
moons: {
$resolve: (val = ["moon"]) => [].concat(val),
$schema: {
title: "planet moons",
},
},
},
};import { resolveSchema, generateTypes } from "untyped";
const types = generateTypes(await resolveSchema(defaultPlanet));
console.log(types)interface Untyped {
/** @default "earth" */
name: string;
specs: {
/** @default 9.8 */
gravity: number;
/**
* planet moons
* @default ["moon"]
*/
moons: string[];
};
}ts-reset ---> 提高一些 JS API 的类型体验
- 👍
.json(infetch) andJSON.parseboth returnunknown - ✅
.filter(Boolean)behaves EXACTLY how you expect - 🥹
array.includesis widened to be more ergonomic - 🚀 And several more changes!
安装
$ npm i -D @total-typescript/ts-reset
使用
import "@total-typescript/ts-reset";ts-morph ---> TS TYPE AST
Parse TS source code to ast. ts-ast-viewer here.
import { Project } from "ts-morph";
const project = new Project();
const sourceFile = project.createSourceFile('validate.ts', tsCode);
const tsTypeString = file.getTypeAlias(item.name) || file.getInterface(item.name) || file.getEnum(item.name)string-ts ---> Strongly typed string functions
import { replace } from 'string-ts'
const str = 'hello-world'
const result = replace(str, '-', ' ')
// ^ 'hello world'