├── .npmignore ├── docs ├── .vitepress │ ├── configs │ │ ├── index.ts │ │ └── sidebar.ts │ ├── theme │ │ ├── styles │ │ │ └── custom.css │ │ ├── index.ts │ │ └── components │ │ │ └── TypeInfo.vue │ ├── config.mts │ └── pages │ │ └── types.json ├── public │ ├── favicon.ico │ └── logo.svg ├── types │ ├── example-vue.md │ ├── example-react.md │ ├── equal.md │ ├── nullable.md │ ├── non-undefined.md │ ├── two-tuple.md │ ├── deep-keys.md │ ├── mutable.md │ ├── camel-case.md │ ├── kebab-case.md │ ├── snake-case.md │ ├── pascal-case.md │ ├── tuple-head.md │ ├── optional-tuple-last.md │ ├── expect.md │ ├── omit-never.md │ ├── required-keys.md │ ├── diff.md │ ├── readonly-keys.md │ ├── intersection.md │ ├── mutable-keys.md │ ├── non-object-keys.md │ ├── record-union.md │ ├── object-keys.md │ ├── function-keys.md │ ├── merge-all.md │ ├── non-function-keys.md │ ├── merge-left-all.md │ ├── merge-right-all.md │ ├── pick-by-required.md │ ├── partial-keys.md │ ├── to-emits-for-events.md │ ├── to-maybe-ref-or-getters.md │ ├── deep-required.md │ ├── merge.md │ ├── merge-left.md │ ├── merge-right.md │ ├── deep-mutable.md │ ├── deep-readonly.md │ ├── deep-partial.md │ ├── readonly-x.md │ ├── to-maybe-ref-or-getters-for-non-function.md │ ├── mutable-x.md │ ├── omit-by-type.md │ ├── pick-by-type.md │ ├── deep-readonly-x.md │ ├── omit-by-type-fuzzy.md │ ├── pick-by-type-exact.md │ ├── pick-by-type-fuzzy.md │ ├── partial-x.md │ ├── required-x.md │ ├── omit-by-type-exact.md │ ├── union-to-intersection.md │ └── curried.md ├── vite.config.ts ├── guide │ └── index.md ├── unocss.config.ts ├── package.json └── index.md ├── packages ├── react │ ├── index.d.ts │ ├── StateReturnType │ │ └── index.d.ts │ └── package.json ├── core │ ├── Optional │ │ └── index.d.ts │ ├── TwoTuple │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── Nullable │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── NonUndefined │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── Mutable │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── OptionalTupleLast │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── Intersection │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── Diff │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── SnakeCase │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── KebabCase │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── OmitNever │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── RequiredKeys │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── NonObjectKeys │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── MutableKeys │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── PartialKeys │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── ReadonlyKeys │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── CamelCase │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── DeepKeys │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── NonFunctionKeys │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── FunctionKeys │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── PascalCase │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── UnionToIntersection │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── PickByRequired │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── ObjectKeys │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── DeepMutable │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── DeepReadonly │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── package.json │ ├── PickByType │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── PartialX │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── RequiredX │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── PickByTypeExact │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── ReadonlyX │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── DeepPartial │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── OmitByType │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── MutableX │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── OmitByTypeFuzzy │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── PickByTypeFuzzy │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── OmitByTypeExact │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── DeepRequired │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── MergeAll │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── Curried │ │ ├── index.d.ts │ │ └── index.test.ts │ ├── DeepReadonlyX │ │ ├── index.d.ts │ │ └── index.d.test.ts │ ├── index.d.ts │ └── Merge │ │ ├── index.d.test.ts │ │ └── index.d.ts ├── shared │ ├── utils │ │ ├── helper.d.ts │ │ └── index.d.ts │ ├── ObjectKeyType │ │ └── index.d.ts │ ├── index.d.ts │ ├── OnlyObject │ │ └── index.d.ts │ ├── Keys │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── RecordToUnion │ │ ├── index.d.test.ts │ │ └── index.d.ts │ ├── package.json │ └── TupleHead │ │ ├── index.d.ts │ │ └── index.d.test.ts └── vue │ ├── index.d.ts │ ├── ToEmitsForEvents │ ├── index.d.test.ts │ └── index.d.ts │ ├── package.json │ ├── ToMaybeRefOrGetters │ └── index.d.ts │ └── ToMaybeRefOrGettersForNonFunction │ └── index.d.ts ├── pnpm-workspace.yaml ├── .vscode └── settings.json ├── .gitignore ├── examples ├── basic │ ├── README.md │ ├── src │ │ ├── user.ts │ │ └── index.ts │ ├── package.json │ ├── test │ │ └── index.test.ts │ └── tsconfig.json └── README.md ├── tsconfig.json ├── index.d.ts ├── package.json ├── tsconfig.base.json ├── LICENSE ├── CONTRIBUTING.md ├── CODE_OF_CONDUCT.md └── README.md /.npmignore: -------------------------------------------------------------------------------- 1 | docs/ -------------------------------------------------------------------------------- /docs/.vitepress/configs/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sidebar' 2 | -------------------------------------------------------------------------------- /packages/react/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './StateReturnType' 2 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - packages/* 3 | - docs 4 | - examples/* -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": ["Twoslash", "utype", "vitepress"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache 2 | .DS_Store 3 | .idea 4 | dist 5 | node_modules 6 | 7 | docs/.vitepress/cache/ -------------------------------------------------------------------------------- /docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzc520pyfm/utype/HEAD/docs/public/favicon.ico -------------------------------------------------------------------------------- /examples/basic/README.md: -------------------------------------------------------------------------------- 1 | # UType Basic Demo 2 | 3 | Run `npm run ts-check` to check type. 4 | -------------------------------------------------------------------------------- /docs/types/example-vue.md: -------------------------------------------------------------------------------- 1 | 2 | # Example Vue 3 | 4 | ## 🤔 What are the commonly used types in Vue? 5 | -------------------------------------------------------------------------------- /docs/types/example-react.md: -------------------------------------------------------------------------------- 1 | 2 | # Example React 3 | 4 | ## 🤔 What are the commonly used types in React? 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "@utype/core"; 2 | export * from "@utype/react"; 3 | // export * from '@utype/vue' 4 | export * from "@utype/shared"; 5 | -------------------------------------------------------------------------------- /packages/core/Optional/index.d.ts: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Optional 4 | * @description Alias for Partial 5 | */ 6 | export type Optional = Partial -------------------------------------------------------------------------------- /examples/basic/src/user.ts: -------------------------------------------------------------------------------- 1 | export interface User { 2 | readonly name: string; 3 | readonly age: number; 4 | readonly visible?: boolean; 5 | } 6 | -------------------------------------------------------------------------------- /examples/basic/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { User } from './user'; 2 | import type { Mutable } from '@utype/core' 3 | 4 | export type MutableUser = Mutable 5 | -------------------------------------------------------------------------------- /packages/shared/utils/helper.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Duplicate 3 | * @description Get copy of `T` 4 | */ 5 | export type Duplicate = { [P in keyof T]: T[P]; } 6 | -------------------------------------------------------------------------------- /packages/vue/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './ToMaybeRefOrGetters' 2 | export * from './ToMaybeRefOrGettersForNonFunction' 3 | export * from './ToEmitsForEvents' 4 | -------------------------------------------------------------------------------- /docs/vite.config.ts: -------------------------------------------------------------------------------- 1 | // vite.config.ts 2 | import UnoCSS from 'unocss/vite' 3 | import { defineConfig } from 'vite' 4 | 5 | export default defineConfig({ 6 | plugins: [ 7 | UnoCSS(), 8 | ], 9 | }) -------------------------------------------------------------------------------- /packages/shared/ObjectKeyType/index.d.ts: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * ObjectKeyType 4 | * @description The Type that can be specified as object keys. 5 | */ 6 | export type ObjectKeyType = string | number | symbol -------------------------------------------------------------------------------- /packages/shared/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./Keys"; 2 | export * from "./ObjectKeyType"; 3 | export * from "./OnlyObject"; 4 | export * from "./TupleHead"; 5 | export * from "./RecordToUnion"; 6 | export * from "./utils"; 7 | -------------------------------------------------------------------------------- /packages/react/StateReturnType/index.d.ts: -------------------------------------------------------------------------------- 1 | import type { useState } from 'react' 2 | 3 | /** 4 | * StateReturnType 5 | * @description Get the return type of React.useState. 6 | */ 7 | export type StateReturnType = ReturnType> 8 | -------------------------------------------------------------------------------- /docs/types/equal.md: -------------------------------------------------------------------------------- 1 | 2 | # Equal 3 | 4 | Compare whether two types are equal. 5 | 6 | ## Usage 7 | 8 | ```ts{3} twoslash 9 | import type { Equal } from '@utype/shared' 10 | 11 | // Expect: false 12 | type Case = Equal 13 | ``` 14 | -------------------------------------------------------------------------------- /packages/core/TwoTuple/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { TwoTuple } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case = [string, string]; 5 | type TwoTupleCase = TwoTuple; 6 | 7 | type cases = [Expect>]; 8 | -------------------------------------------------------------------------------- /packages/shared/OnlyObject/index.d.ts: -------------------------------------------------------------------------------- 1 | import { ObjectKeyType } from "@utype/shared"; 2 | 3 | /** 4 | * OnlyObject 5 | * @description Declare object, excluding Array, Map, Set, RegExp, Date, null, etc. 6 | */ 7 | export type OnlyObject = Record; 8 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | | Example | Source | 2 | | ------- | ---------------------------------------------------------------------- | 3 | | `basic` | [Github](https://github.com/wzc520pyfm/utype/tree/main/examples/basic) | 4 | -------------------------------------------------------------------------------- /packages/core/Nullable/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { Nullable } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = string; 5 | type NullableCase1 = string | null | undefined; 6 | 7 | type cases = [Expect, NullableCase1>>]; 8 | -------------------------------------------------------------------------------- /packages/core/TwoTuple/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * TwoTuple 3 | * @description A Tuple consisting of two identical types. 4 | * @example 5 | * ```ts 6 | * // Expect: [string, string] 7 | * type TestType = TwoTuple 8 | * ``` 9 | */ 10 | export type TwoTuple = [T, T] 11 | -------------------------------------------------------------------------------- /packages/core/Nullable/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Nullable 3 | * @description Maybe null or undefined from set T. 4 | * @example 5 | * ```ts 6 | * // Expect: string | null | undefined 7 | * type Ref = Nullable 8 | * ``` 9 | */ 10 | export type Nullable = T | null | undefined 11 | -------------------------------------------------------------------------------- /packages/core/NonUndefined/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * NonUndefined 3 | * @description Exclude undefined from set T. 4 | * @example 5 | * ```ts 6 | * // Expect: string 7 | * type Ref = NonUndefined 8 | * ``` 9 | */ 10 | export type NonUndefined = T extends undefined ? never : T 11 | -------------------------------------------------------------------------------- /packages/shared/Keys/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import { Keys, Equal, Expect } from "@utype/shared"; 2 | 3 | type Case1 = { 4 | readonly name: string; 5 | age: number; 6 | visible: boolean; 7 | }; 8 | type KeysCase1 = "name" | "age" | "visible"; 9 | 10 | type cases = [Expect, KeysCase1>>]; 11 | -------------------------------------------------------------------------------- /examples/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@utype/example-basic", 3 | "private": true, 4 | "license": "MIT", 5 | "scripts": { 6 | "ts-check": "tsc" 7 | }, 8 | "devDependencies": { 9 | "typescript": "^5.3.3", 10 | "@utype/core": "latest", 11 | "@utype/shared": "latest" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/basic/test/index.test.ts: -------------------------------------------------------------------------------- 1 | import type { MutableUser } from "../src"; 2 | import type { Expect, Equal } from "@utype/shared"; 3 | 4 | type MutableCase = { 5 | name: string; 6 | age: number; 7 | visible?: boolean; 8 | } 9 | 10 | type cases = [ 11 | Expect> 12 | ] 13 | -------------------------------------------------------------------------------- /packages/core/Mutable/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { Mutable } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case = { 5 | name: string; 6 | }; 7 | type ReadonlyCase = { 8 | readonly name: string; 9 | }; 10 | 11 | type cases = [Expect, Case>>]; 12 | -------------------------------------------------------------------------------- /examples/basic/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "node16", 5 | "strict": true, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "sourceMap": true, 9 | "verbatimModuleSyntax": true 10 | }, 11 | "include": ["src", "test"], 12 | "exclude": ["node_modules"] 13 | } 14 | -------------------------------------------------------------------------------- /docs/types/nullable.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Basic Operation 3 | --- 4 | 5 | # Nullable 6 | 7 | 8 | 9 | Maybe null or undefined from set T. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { Nullable } from '@utype/core' 15 | 16 | // Expect: string | null | undefined // [!code highlight] 17 | type Ref = Nullable 18 | ``` 19 | -------------------------------------------------------------------------------- /packages/core/Mutable/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Mutable 3 | * @description Like Readonly, but it will remove the readonly of the object property. 4 | * @example 5 | * ```ts 6 | * type Prop = { readonly name: string } 7 | * // Expect: { name: string } 8 | * type MutableProp = Mutable 9 | * ``` 10 | */ 11 | export type Mutable = { -readonly [P in keyof T]: T[P]; } 12 | -------------------------------------------------------------------------------- /docs/types/non-undefined.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Basic Operation 3 | --- 4 | 5 | # NonUndefined 6 | 7 | 8 | 9 | Exclude undefined from set T. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { NonUndefined } from '@utype/core' 15 | 16 | // Expect: string // [!code highlight] 17 | type Ref = NonUndefined 18 | ``` 19 | -------------------------------------------------------------------------------- /docs/types/two-tuple.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Basic Operation 3 | --- 4 | 5 | # TwoTuple 6 | 7 | 8 | 9 | A Tuple consisting of two identical types. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { TwoTuple } from '@utype/core' 15 | 16 | // Expect: [string, string] // [!code highlight] 17 | type TestType = TwoTuple 18 | ``` 19 | -------------------------------------------------------------------------------- /packages/shared/Keys/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Keys 3 | * @description Consistent with keyof. Get union type of all keys in object type T. 4 | * @example 5 | * ```ts 6 | * type Prop = { 7 | * name: string; 8 | * age: number; 9 | * getName: () => string; 10 | * } 11 | * // Expect: 'name' | 'age' | 'getName' 12 | * type KeysProp = Keys 13 | * ``` 14 | */ 15 | export type Keys = keyof T; 16 | -------------------------------------------------------------------------------- /packages/core/OptionalTupleLast/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * OptionalTupleLast 3 | * @description Make the last element of a tuple optional. 4 | * @example 5 | * ```ts 6 | * type Tuple = [string, number, boolean]; 7 | * // Expect: [string, number, boolean?] 8 | * type OptionalTuple = OptionalTupleLast; 9 | * ``` 10 | */ 11 | export type OptionalTupleLast = T extends [...infer U, infer L] 12 | ? [...U, L?] 13 | : never; 14 | -------------------------------------------------------------------------------- /docs/types/deep-keys.md: -------------------------------------------------------------------------------- 1 | 2 | # DeepKeys 3 | 4 | Get the union type composed of all keys from nested objects. 5 | 6 | ## Usage 7 | 8 | ```ts twoslash 9 | import type { DeepKeys } from '@utype/core' 10 | 11 | type Props = { 12 | a: string; 13 | b: number; 14 | c: { 15 | d: { 16 | e: string; 17 | } 18 | } 19 | } 20 | 21 | // Expect: 'a' | 'b' | 'c' | 'd' | 'e' // [!code highlight] 22 | type DeepKeysProps = DeepKeys 23 | ``` 24 | -------------------------------------------------------------------------------- /packages/core/Intersection/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { Intersection } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case = { 5 | name: string; 6 | age: number; 7 | visible: boolean; 8 | }; 9 | type DefaultCase = { 10 | age: number; 11 | sex: string; 12 | }; 13 | type IntersectionCase = { 14 | age: number; 15 | }; 16 | 17 | type cases = [Expect, IntersectionCase>>]; 18 | -------------------------------------------------------------------------------- /packages/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@utype/react", 3 | "version": "0.0.5", 4 | "description": "", 5 | "main": "", 6 | "types": "index.d.ts", 7 | "scripts": { 8 | "test": "tsc" 9 | }, 10 | "keywords": [ 11 | "utility", 12 | "typescript", 13 | "types", 14 | "utility types" 15 | ], 16 | "author": "wzc520pyfm", 17 | "license": "MIT", 18 | "dependencies": { 19 | "@types/react": "^18.2.45" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /docs/types/mutable.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Object Operation 3 | --- 4 | 5 | # Mutable 6 | 7 | 8 | 9 | Like Readonly, but it will remove the readonly of the object property. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { Mutable } from '@utype/core' 15 | 16 | type Props = { readonly name: string; } 17 | 18 | // Expect: { name: string } // [!code highlight] 19 | type MutableProps = Mutable 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/types/camel-case.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: String Operation 3 | --- 4 | 5 | # CamelCase 6 | 7 | 8 | 9 | Replace the snake_case or kebab-case string with camelCase. 10 | 11 | ## Usage 12 | 13 | ```ts{3,5} twoslash 14 | import type { CamelCase } from '@utype/core' 15 | 16 | // Expect: "fooBarBaz" 17 | type FooBarBaz = CamelCase<"foo_bar_baz"> 18 | // Expect: "fooBarBaz" 19 | type FooBarBaz2 = CamelCase<"foo-bar-baz"> 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/types/kebab-case.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: String Operation 3 | --- 4 | 5 | # KebabCase 6 | 7 | 8 | 9 | Replace the camelCase or PascalCase string with kebab-case. 10 | 11 | ## Usage 12 | 13 | ```ts{3,5} twoslash 14 | import type { KebabCase } from '@utype/core' 15 | 16 | // Expect: "foo-bar-baz" 17 | type FooBarBaz = KebabCase<"fooBarBaz"> 18 | // Expect: "foo-bar-baz" 19 | type FooBarBaz2 = KebabCase<"FooBarBaz"> 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/types/snake-case.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: String Operation 3 | --- 4 | 5 | # SnakeCase 6 | 7 | 8 | 9 | Replace the camelCase or PascalCase string with snake_case. 10 | 11 | ## Usage 12 | 13 | ```ts{3,5} twoslash 14 | import type { SnakeCase } from '@utype/core' 15 | 16 | // Expect: "foo_bar_baz" 17 | type FooBarBaz = SnakeCase<"fooBarBaz"> 18 | // Expect: "foo_bar_baz" 19 | type FooBarBaz2 = SnakeCase<"FooBarBaz"> 20 | ``` 21 | -------------------------------------------------------------------------------- /packages/core/NonUndefined/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { NonUndefined } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = string | undefined; 5 | type NonUndefinedCase1 = string; 6 | 7 | type Case2 = string | number[] | undefined; 8 | type NonUndefinedCase2 = string | number[]; 9 | 10 | type cases = [ 11 | Expect, NonUndefinedCase1>>, 12 | Expect, NonUndefinedCase2>> 13 | ]; 14 | -------------------------------------------------------------------------------- /docs/types/pascal-case.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: String Operation 3 | --- 4 | 5 | # PascalCase 6 | 7 | 8 | 9 | Replace the snake_case or kebab-case string with PascalCase. 10 | 11 | ## Usage 12 | 13 | ```ts{3,5} twoslash 14 | import type { PascalCase } from '@utype/core' 15 | 16 | // Expect: "FooBarBaz" 17 | type FooBarBaz = PascalCase<"foo_bar_baz"> 18 | // Expect: "FooBarBaz" 19 | type FooBarBaz2 = PascalCase<"foo-bar-baz"> 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/types/tuple-head.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: \- 3 | alias: FirstAsTuple 4 | --- 5 | 6 | # TupleHead 7 | 8 | 9 | 10 | Extracting the first element of a tuple as a tuple type. 11 | 12 | ## Usage 13 | 14 | ```ts twoslash 15 | import type { TupleHead } from '@utype/shared' 16 | 17 | type Prop = [a: string, b: number, c: boolean] 18 | // Expect: [a: string] // [!code highlight] 19 | type TupleHeadProp = TupleHead 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/types/optional-tuple-last.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Basic Operation 3 | --- 4 | 5 | # OptionalTupleLast 6 | 7 | 8 | 9 | Make the last element of a tuple optional. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { OptionalTupleLast } from '@utype/core' 15 | 16 | type Tuple = [string, number, boolean]; 17 | // Expect: [string, number, boolean?] // [!code highlight] 18 | type OptionalTuple = OptionalTupleLast; 19 | ``` 20 | -------------------------------------------------------------------------------- /docs/types/expect.md: -------------------------------------------------------------------------------- 1 | 2 | # Expect 3 | 4 | Only accept the 'true' type, typically used to determine if the result returned by 'Equal' is true. 5 | 6 | ## Usage 7 | 8 | ```ts twoslash 9 | import type { Expect, Equal } from '@utype/shared' 10 | 11 | // @ts-expect-error 12 | type Case = Expect // [!code error] 13 | // @ts-expect-error 14 | type Case2 = Expect> // [!code error] 15 | // Expect 16 | type Case3 = Expect> // [!code highlight] 17 | ``` 18 | -------------------------------------------------------------------------------- /packages/core/Diff/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { Diff } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case = { 5 | name: string; 6 | age: number; 7 | visible: boolean; 8 | }; 9 | type DefaultCase = { 10 | age: number; 11 | sex: string; 12 | }; 13 | type DiffCase = { 14 | name: string; 15 | visible: boolean; 16 | sex: string; 17 | }; 18 | 19 | type TT = Diff 20 | 21 | type cases = [Expect, DiffCase>>]; -------------------------------------------------------------------------------- /packages/core/OptionalTupleLast/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { OptionalTupleLast } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = [string, number, boolean]; 5 | type OptionalTupleCase1 = [string, number, boolean?]; 6 | 7 | type Case2 = [string, number]; 8 | type OptionalTupleCase2 = [string, number?]; 9 | 10 | type cases = [ 11 | Expect, OptionalTupleCase1>>, 12 | Expect, OptionalTupleCase2>> 13 | ]; 14 | -------------------------------------------------------------------------------- /packages/vue/ToEmitsForEvents/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { ToEmitsForEvents } from "@utype/vue"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type EventsCase = { 5 | onPress?: (e: Event) => void 6 | onPressStart: (e: Event, str?: string) => void 7 | }; 8 | type EmitsCase = { 9 | (eventname: "press", e: Event): void 10 | } & { 11 | (eventname: "pressstart", e: Event, str?: string): void 12 | }; 13 | 14 | type cases = [ 15 | Expect, EmitsCase>> 16 | ]; 17 | -------------------------------------------------------------------------------- /docs/types/omit-never.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Basic Operation 3 | --- 4 | 5 | # OmitNever 6 | 7 | 8 | 9 | Get Union type of object property types, but filtered out never types. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { OmitNever } from '@utype/core' 15 | 16 | type Props = { 17 | name: string; 18 | age: never; 19 | visible: boolean; 20 | } 21 | 22 | // Expect: string | boolean // [!code highlight] 23 | type OmitNeverProps = OmitNever 24 | ``` 25 | -------------------------------------------------------------------------------- /packages/core/Intersection/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Keys } from "@utype/shared"; 2 | 3 | /** 4 | * Intersection 5 | * @description From T pick properties that exist in U. 6 | * @example 7 | * ```ts 8 | * type Prop = { name: string; age: number; visible: boolean } 9 | * type DefaultProps = { age: number; sex: string } 10 | * // Expect: { age: number; } 11 | * type IntersectionProp = Intersection 12 | * ``` 13 | */ 14 | export type Intersection = Pick, Keys>>; 15 | -------------------------------------------------------------------------------- /packages/vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@utype/vue", 3 | "version": "0.0.5", 4 | "description": "", 5 | "main": "", 6 | "types": "index.d.ts", 7 | "scripts": { 8 | "test": "tsc" 9 | }, 10 | "keywords": [ 11 | "utility", 12 | "typescript", 13 | "types", 14 | "utility types" 15 | ], 16 | "author": "wzc520pyfm", 17 | "license": "MIT", 18 | "dependencies": { 19 | "@utype/core": "workspace:^", 20 | "@utype/shared": "workspace:^", 21 | "vue": "^3.4.21" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /docs/types/required-keys.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Get Object Keys 3 | --- 4 | 5 | # RequiredKeys 6 | 7 | 8 | 9 | Get union type of keys that are required in object type T. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { RequiredKeys } from '@utype/core' 15 | 16 | type Props = { 17 | name: string; 18 | age: number; 19 | visible?: boolean; 20 | } 21 | 22 | // Expect: 'name' | 'age' // [!code highlight] 23 | type RequiredKeysProps = RequiredKeys 24 | ``` 25 | -------------------------------------------------------------------------------- /packages/shared/RecordToUnion/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { RecordToUnion } from "@utype/shared"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { name: string; visible: boolean; }; 5 | type RecordToUnionCase1 = string | boolean 6 | 7 | type Case2 = { name: string; visible?: boolean; }; 8 | type RecordToUnionCase2 = string | boolean | undefined 9 | 10 | type cases = [ 11 | Expect, RecordToUnionCase1>>, 12 | Expect, RecordToUnionCase2>>, 13 | ]; 14 | -------------------------------------------------------------------------------- /docs/types/diff.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Generate Object 3 | --- 4 | 5 | # Diff 6 | 7 | 8 | 9 | Get the types that are not common in both T and U. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { Diff } from '@utype/core' 15 | 16 | type Prop = { name: string; age: number; visible: boolean } 17 | type DefaultProps = { age: number; sex: string } 18 | 19 | // Expect: { name: string; visible: boolean; sex: string } // [!code highlight] 20 | type DiffProp = Diff 21 | ``` -------------------------------------------------------------------------------- /docs/types/readonly-keys.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Get Object Keys 3 | --- 4 | 5 | # ReadonlyKeys 6 | 7 | 8 | 9 | Get union type of keys that are readonly in object type T. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { ReadonlyKeys } from '@utype/core' 15 | 16 | type Props = { 17 | readonly name: string; 18 | readonly age: number; 19 | visible: boolean; 20 | } 21 | 22 | // Expect: 'name' | 'age' // [!code highlight] 23 | type ReadonlyKeysProps = ReadonlyKeys 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/types/intersection.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Generate Object 3 | --- 4 | 5 | # Intersection 6 | 7 | 8 | 9 | From T pick properties that exist in U. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { Intersection } from '@utype/core' 15 | 16 | type Props = { name: string; age: number; visible: boolean } 17 | type DefaultProps = { age: number; sex: string } 18 | 19 | // Expect: { age: number; } // [!code highlight] 20 | type IntersectionProps = Intersection 21 | ``` 22 | -------------------------------------------------------------------------------- /docs/types/mutable-keys.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Get Object Keys 3 | --- 4 | 5 | # MutableKeys 6 | 7 | 8 | 9 | Get union type of keys that are mutable (not readonly) in object type T. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { MutableKeys } from '@utype/core' 15 | 16 | type Props = { 17 | readonly name: string; 18 | age: number; 19 | visible: boolean; 20 | } 21 | 22 | // Expect: 'age' | 'visible' // [!code highlight] 23 | type MutableKeysProps = MutableKeys 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/types/non-object-keys.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Get Object Keys 3 | --- 4 | 5 | # NonObjectKeys 6 | 7 | 8 | 9 | Get union type of keys that are non-object in object type T. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { NonObjectKeys } from '@utype/core' 15 | 16 | type Props = { 17 | name: string; 18 | age: number; 19 | breakfast: { foods: string[]; }; 20 | } 21 | 22 | // Expect: 'name' | 'age' // [!code highlight] 23 | type NonObjectKeysProps = NonObjectKeys 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/types/record-union.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Basic Operation 3 | alias: Record2Union RToU R2U 4 | --- 5 | 6 | # RecordToUnion 7 | 8 | 9 | 10 | Get union type given record type U. 11 | 12 | ## Usage 13 | 14 | ```ts twoslash 15 | import type { RecordToUnion } from '@utype/shared' 16 | 17 | type Props = { name: string; visible: boolean; } 18 | 19 | // Expect: string | boolean // [!code highlight] 20 | type RecordToUnionProps = RecordToUnion 21 | ``` 22 | -------------------------------------------------------------------------------- /docs/types/object-keys.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Get Object Keys 3 | --- 4 | 5 | # ObjectKeys 6 | 7 | 8 | 9 | Get union type of keys that are object in object type T. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { ObjectKeys } from '@utype/core' 15 | 16 | type Props = { 17 | name: string; 18 | breakfast: { foods: string[]; }; 19 | dinner: { foods: string[]; }; 20 | } 21 | 22 | // Expect: 'breakfast' | 'dinner' // [!code highlight] 23 | type ObjectKeysProps = ObjectKeys 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/types/function-keys.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Get Object Keys 3 | --- 4 | 5 | # FunctionKeys 6 | 7 | 8 | 9 | Get union type of keys that are functions in object type T. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { FunctionKeys } from '@utype/core' 15 | 16 | type Props = { 17 | name: string; 18 | setName: (name: string) => void; 19 | getName: () => string; 20 | } 21 | 22 | // Expect: 'setName' | 'getName' // [!code highlight] 23 | type FunctionKeysProps = FunctionKeys 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/styles/custom.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --vp-c-brand-1: #52730d; 3 | --vp-c-brand-2: #57791b; 4 | --vp-c-brand-3: #506e10; 5 | --vp-home-hero-name-color: transparent; 6 | --vp-home-hero-name-background: -webkit-linear-gradient( 7 | 120deg, 8 | #86b91a 30%, 9 | #edd532 10 | ); 11 | --vp-home-hero-image-background-image: linear-gradient( 12 | -45deg, 13 | #86b91a60 30%, 14 | #edd53260 15 | ); 16 | --vp-home-hero-image-filter: blur(72px); 17 | --vp-code-line-highlight-color: var(--vp-c-green-soft); 18 | } 19 | -------------------------------------------------------------------------------- /docs/types/merge-all.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Merge Object 3 | --- 4 | 5 | # MergeAll 6 | 7 | 8 | 9 | Merge variadic number of types into a new type. If the keys overlap, its values should be merged into an union. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { MergeAll } from '@utype/core' 15 | 16 | type Foo = { a: 1; b: 2 } 17 | type Bar = { a: 2 } 18 | type Baz = { c: 3 } 19 | 20 | // Expect: { a: 1 | 2; b: 2; c: 3 } // [!code highlight] 21 | type MergeAllResult = MergeAll<[Foo, Bar, Baz]> 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/types/non-function-keys.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Get Object Keys 3 | --- 4 | 5 | # NonFunctionKeys 6 | 7 | 8 | 9 | Get union type of keys that are non-functions in object type T. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { NonFunctionKeys } from '@utype/core' 15 | 16 | type Props = { 17 | name: string; 18 | age: number; 19 | setName: (name: string) => void; 20 | } 21 | 22 | // Expect: 'name' | 'age' // [!code highlight] 23 | type NonFunctionKeysProps = NonFunctionKeys 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/types/merge-left-all.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Merge Object 3 | --- 4 | 5 | # MergeLeftAll 6 | 7 | 8 | 9 | Merge variadic number of types into a new type. If the keys overlap, earlier keys override later keys. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { MergeLeftAll } from '@utype/core' 15 | 16 | type Foo = { a: 1; b: 2 } 17 | type Bar = { a: 2 } 18 | type Baz = { c: 3 } 19 | 20 | // Expect: { a: 1; b: 2; c: 3 } // [!code highlight] 21 | type MergeLeftAllResult = MergeLeftAll<[Foo, Bar, Baz]> 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/types/merge-right-all.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Merge Object 3 | --- 4 | 5 | # MergeRightAll 6 | 7 | 8 | 9 | Merge variadic number of types into a new type. If the keys overlap, later keys override earlier keys. 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { MergeRightAll } from '@utype/core' 15 | 16 | type Foo = { a: 1; b: 2 } 17 | type Bar = { a: 2 } 18 | type Baz = { c: 3 } 19 | 20 | // Expect: { a: 2; b: 2; c: 3 } // [!code highlight] 21 | type MergeRightAllResult = MergeRightAll<[Foo, Bar, Baz]> 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/types/pick-by-required.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Generate Object 3 | alias: GetRequired 4 | --- 5 | 6 | # PickByRequired 7 | 8 | 9 | 10 | From T pick all required properties to generate a new object type. 11 | 12 | ## Usage 13 | 14 | ```ts twoslash 15 | import type { PickByRequired } from '@utype/core' 16 | 17 | type Props = { 18 | foo: number; 19 | bar?: string; 20 | } 21 | 22 | // Expect: { foo: number; } // [!code highlight] 23 | type PickByRequiredProps = PickByRequired 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/types/partial-keys.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Get Object Keys 3 | alias: OptionalKeys 4 | --- 5 | 6 | # PartialKeys 7 | 8 | 9 | 10 | Get union type of keys that are partial in object type T. 11 | 12 | ## Usage 13 | 14 | ```ts twoslash 15 | import type { PartialKeys } from '@utype/core' 16 | 17 | type Props = { 18 | name: string; 19 | age?: number; 20 | visible?: boolean; 21 | } 22 | 23 | // Expect: 'age' | 'visible' // [!code highlight] 24 | type PartialKeysProps = PartialKeys 25 | ``` 26 | -------------------------------------------------------------------------------- /packages/core/SnakeCase/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SnakeCase 3 | * @description Replace the camelCase or PascalCase string with snake_case. 4 | * @example 5 | * ```ts 6 | * // Expect: "foo_bar_baz" 7 | * type FooBarBaz = SnakeCase<"fooBarBaz"> 8 | * // Expect: "foo_bar_baz" 9 | * type FooBarBaz2 = SnakeCase<"FooBarBaz"> 10 | * ``` 11 | */ 12 | export type SnakeCase = S extends `${infer S1}${infer S2}` 13 | ? S2 extends Uncapitalize 14 | ? `${Uncapitalize}${SnakeCase}` 15 | : `${Uncapitalize}_${SnakeCase}` 16 | : S; 17 | -------------------------------------------------------------------------------- /packages/core/KebabCase/index.d.ts: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * KebabCase 4 | * @description Replace the camelCase or PascalCase string with kebab-case. 5 | * @example 6 | * ```ts 7 | * // Expect: "foo-bar-baz" 8 | * type FooBarBaz = KebabCase<"fooBarBaz"> 9 | * // Expect: "foo-bar-baz" 10 | * type FooBarBaz2 = KebabCase<"FooBarBaz"> 11 | * ``` 12 | */ 13 | export type KebabCase = S extends `${infer S1}${infer S2}` 14 | ? S2 extends Uncapitalize 15 | ? `${Uncapitalize}${KebabCase}` 16 | : `${Uncapitalize}-${KebabCase}` 17 | : S; 18 | -------------------------------------------------------------------------------- /packages/core/SnakeCase/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { SnakeCase } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type cases = [ 5 | Expect, "hello">>, 6 | Expect, "user_name">>, 7 | Expect, "user_pwd">>, 8 | Expect, "get_element_by_id">>, 9 | Expect< 10 | Equal< 11 | SnakeCase<"getElementById" | "getElementByClassNames">, 12 | "get_element_by_id" | "get_element_by_class_names" 13 | > 14 | > 15 | ]; 16 | -------------------------------------------------------------------------------- /packages/core/OmitNever/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { OmitNever } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | name: string; 6 | age: never; 7 | visible: boolean; 8 | }; 9 | type OmitNeverCase1 = string | boolean; 10 | 11 | type Case2 = { 12 | readonly name: "Alice"; 13 | readonly age: "40"; 14 | }; 15 | type OmitNeverCase2 = "Alice" | "40"; 16 | type TT = OmitNever; 17 | 18 | type cases = [ 19 | Expect, OmitNeverCase1>>, 20 | Expect, OmitNeverCase2>> 21 | ]; 22 | -------------------------------------------------------------------------------- /packages/core/RequiredKeys/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { RequiredKeys } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | name: string; 6 | age?: number; 7 | visible?: boolean; 8 | }; 9 | type RequiredKeysCase1 = "name"; 10 | 11 | type Case2 = { 12 | name: string; 13 | readonly age: number; 14 | visible?: boolean; 15 | }; 16 | type RequiredKeysCase2 = "name" | "age"; 17 | 18 | type cases = [ 19 | Expect, RequiredKeysCase1>>, 20 | Expect, RequiredKeysCase2>> 21 | ]; 22 | -------------------------------------------------------------------------------- /packages/core/NonObjectKeys/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Keys } from "@utype/shared"; 2 | import { ObjectKeys } from "@utype/core"; 3 | 4 | /** 5 | * NonObjectKeys 6 | * @description Get union type of keys that are non-object in object type T. 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * name: string; 11 | * age: number; 12 | * breakfast: { foods: string[]; }; 13 | * } 14 | * // Expect: 'name' | 'age' 15 | * type NonObjectKeysProp = NonObjectKeys 16 | * ``` 17 | */ 18 | export type NonObjectKeys = Exclude, ObjectKeys>; 19 | -------------------------------------------------------------------------------- /packages/core/MutableKeys/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { MutableKeys } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | name: string; 6 | readonly age: number; 7 | readonly visible: boolean; 8 | }; 9 | type MutableKeysCase1 = "name"; 10 | 11 | type Case2 = { 12 | name: string; 13 | age: number; 14 | readonly visible?: boolean; 15 | }; 16 | type MutableKeysCase2 = "name" | "age"; 17 | 18 | type cases = [ 19 | Expect, MutableKeysCase1>>, 20 | Expect, MutableKeysCase2>> 21 | ]; 22 | -------------------------------------------------------------------------------- /docs/types/to-emits-for-events.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Reactive 3 | alias: ToEmitsForEvents 4 | --- 5 | 6 | # ToEmitsForEvents 7 | 8 | 9 | 10 | Converting Events to Emits. 11 | 12 | ## Usage 13 | 14 | ```ts twoslash 15 | import type { ToEmitsForEvents } from '@utype/vue' 16 | 17 | type Props = { 18 | onClick: (e: Event) => void; 19 | onMousedown: () => void; 20 | } 21 | 22 | // Expect: { (eventname: "click", e: Event): void; (eventname: "mousedown"): void; } // [!code highlight] 23 | type MyProp = ToEmitsForEvents 24 | ``` 25 | -------------------------------------------------------------------------------- /packages/core/PartialKeys/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { PartialKeys } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | name: string; 6 | age?: number; 7 | visible?: boolean; 8 | }; 9 | type PartialKeysCase1 = "age" | "visible"; 10 | 11 | type Case2 = { 12 | readonly name?: string; 13 | readonly age?: number; 14 | visible: boolean; 15 | }; 16 | type PartialKeysCase2 = "name" | "age"; 17 | 18 | type cases = [ 19 | Expect, PartialKeysCase1>>, 20 | Expect, PartialKeysCase2>> 21 | ]; 22 | -------------------------------------------------------------------------------- /packages/core/ReadonlyKeys/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { ReadonlyKeys } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | readonly name: string; 6 | age: number; 7 | visible: boolean; 8 | }; 9 | type ReadonlyKeysCase1 = "name"; 10 | 11 | type Case2 = { 12 | readonly name: string; 13 | readonly age: number; 14 | visible?: boolean; 15 | }; 16 | type ReadonlyKeysCase2 = "name" | "age"; 17 | 18 | type cases = [ 19 | Expect, ReadonlyKeysCase1>>, 20 | Expect, ReadonlyKeysCase2>> 21 | ]; 22 | -------------------------------------------------------------------------------- /packages/core/CamelCase/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * CamelCase 3 | * @description Replace the snake_case or kebab-case string with camelCase. 4 | * @example 5 | * ```ts 6 | * // Expect: "fooBarBaz" 7 | * type FooBarBaz = CamelCase<"foo_bar_baz"> 8 | * // Expect: "fooBarBaz" 9 | * type FooBarBaz = CamelCase<"foo-bar-baz"> 10 | * ``` 11 | */ 12 | // todo need support more edge cases. 13 | export type CamelCase< 14 | S extends string, 15 | sp extends string = "_" | "-" 16 | > = S extends `${infer S1}${sp}${infer S2}` 17 | ? `${Lowercase}${Capitalize>}` 18 | : Lowercase; 19 | -------------------------------------------------------------------------------- /docs/types/to-maybe-ref-or-getters.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Reactive 3 | --- 4 | 5 | # ToMaybeRefOrGetters 6 | 7 | 8 | 9 | Mark the object's property type as [MaybeRefOrGetters](https://vuejs.org/api/utility-types.html#maybereforgetter). 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { ToMaybeRefOrGetters } from "@utype/vue"; 15 | 16 | type Prop = { 17 | name: string; 18 | age: number; 19 | }; 20 | // Expect: { name: MaybeRefOrGetters; age: MaybeRefOrGetters; } // [!code highlight] 21 | type MyProp = ToMaybeRefOrGetters; 22 | ``` 23 | -------------------------------------------------------------------------------- /packages/core/Diff/index.d.ts: -------------------------------------------------------------------------------- 1 | import { MergeLeft } from "@utype/core"; 2 | import { Keys } from "@utype/shared"; 3 | 4 | /** 5 | * Diff 6 | * @description Get the types that are not common in both T and U. 7 | * @example 8 | * ```ts 9 | * type Prop = { name: string; age: number; visible: boolean } 10 | * type DefaultProps = { age: number; sex: string } 11 | * // Expect: { name: string; visible: boolean; sex: string } 12 | * type DiffProp = Diff 13 | * ``` 14 | */ 15 | export type Diff = MergeLeft, Keys>>, Pick, Keys>>>; 16 | -------------------------------------------------------------------------------- /docs/types/deep-required.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Object Operation 3 | --- 4 | 5 | # DeepRequired 6 | 7 | 8 | 9 | Make every parameter of an object - and its sub-objects recursively - required. 10 | 11 | ## Usage 12 | 13 | ```ts{11-17} twoslash 14 | import type { DeepRequired } from '@utype/core' 15 | 16 | type Props = { 17 | x: { 18 | a?: 1 19 | b: 'hi' 20 | }, 21 | y?: 'hey' 22 | } 23 | 24 | // Expect: { 25 | // x: { 26 | // a: 1, 27 | // b: 'hi' 28 | // } 29 | // y: 'hey' 30 | // } 31 | type DeepRequiredProps = DeepRequired 32 | ``` 33 | -------------------------------------------------------------------------------- /packages/core/DeepKeys/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import { DeepKeys } from "@utype/core" 2 | import { Expect, Equal } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | name: string; 6 | age: number; 7 | objCase?: { 8 | a: string; 9 | b: { 10 | c?: string; 11 | }; 12 | }; 13 | }; 14 | type DeepKeysCase1 = "name" | "age" | "objCase" | "a" | "b" | "c"; 15 | 16 | type Case2 = { 17 | name: string; 18 | age: number; 19 | }; 20 | type DeepKeysCase2 = "name" | "age"; 21 | 22 | type cases = [ 23 | Expect, DeepKeysCase1>>, 24 | Expect, DeepKeysCase2>> 25 | ]; 26 | -------------------------------------------------------------------------------- /docs/types/merge.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Merge Object 3 | --- 4 | 5 | # Merge 6 | 7 | 8 | 9 | Merge two types into a new type. If the keys overlap, its values should be merged into an union. 10 | 11 | ## Usage 12 | 13 | ```ts{12-16} twoslash 14 | import type { Merge } from '@utype/core' 15 | 16 | type Foo = { 17 | name: string; 18 | age: string; 19 | } 20 | type Bar = { 21 | age: number; 22 | sex: string; 23 | } 24 | 25 | // Expect: { 26 | // name: string; 27 | // age: number | string; 28 | // sex: string; 29 | // } 30 | type MergeResult = Merge 31 | ``` 32 | -------------------------------------------------------------------------------- /packages/core/KebabCase/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { KebabCase } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type cases = [ 5 | Expect, "foo-bar-baz">>, 6 | Expect, "foo-bar-baz">>, 7 | Expect, "foo-bar">>, 8 | Expect, "foo_bar">>, 9 | Expect, "foo--bar">>, 10 | Expect, "a-b-c">>, 11 | Expect, "-">>, 12 | Expect, "">>, 13 | Expect, "😎">> 14 | ]; 15 | -------------------------------------------------------------------------------- /docs/types/merge-left.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Merge Object 3 | --- 4 | 5 | # MergeLeft 6 | 7 | 8 | 9 | Merge two types into a new type. Keys of the first type overrides keys of the second type. 10 | 11 | ## Usage 12 | 13 | ```ts{12-16} twoslash 14 | import type { MergeLeft } from '@utype/core' 15 | 16 | type Foo = { 17 | name: string; 18 | age: string; 19 | } 20 | type Bar = { 21 | age: number; 22 | sex: string; 23 | } 24 | 25 | // Expect: { 26 | // name: string; 27 | // age: string; 28 | // sex: string; 29 | // } 30 | type MergeLeftResult = MergeLeft 31 | ``` 32 | -------------------------------------------------------------------------------- /packages/core/NonFunctionKeys/index.d.ts: -------------------------------------------------------------------------------- 1 | import { FunctionKeys } from "@utype/core"; 2 | import { Keys } from "@utype/shared"; 3 | 4 | /** 5 | * NonFunctionKeys 6 | * @description Get union type of keys that are non-functions in object type T. 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * name: string; 11 | * age: number; 12 | * setName: (name: string) => void; 13 | * } 14 | * // Expect: 'name' | 'age' 15 | * type NonFunctionKeysProp = NonFunctionKeys 16 | * ``` 17 | */ 18 | export type NonFunctionKeys = Exclude< 19 | Keys, 20 | FunctionKeys 21 | >; 22 | -------------------------------------------------------------------------------- /docs/types/merge-right.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Merge Object 3 | --- 4 | 5 | # MergeRight 6 | 7 | 8 | 9 | Merge two types into a new type. Keys of the second type overrides keys of the first type. 10 | 11 | ## Usage 12 | 13 | ```ts{12-16} twoslash 14 | import type { MergeRight } from '@utype/core' 15 | 16 | type Foo = { 17 | name: string; 18 | age: string; 19 | } 20 | type Bar = { 21 | age: number; 22 | sex: string; 23 | } 24 | 25 | // Expect: { 26 | // name: string; 27 | // age: number; 28 | // sex: string; 29 | // } 30 | type MergeRightResult = MergeRight 31 | ``` 32 | -------------------------------------------------------------------------------- /packages/core/FunctionKeys/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { FunctionKeys } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | name: string; 6 | getName: () => string; 7 | }; 8 | type FunctionKeysCase1 = "getName"; 9 | 10 | type Case2 = { 11 | name: string; 12 | getName: () => string; 13 | setName?: (name: string) => void; 14 | }; 15 | type FunctionKeysCase2 = "setName" | "getName"; 16 | 17 | type TT = FunctionKeys; 18 | 19 | type cases = [ 20 | Expect, FunctionKeysCase1>>, 21 | Expect, FunctionKeysCase2>> 22 | ]; 23 | -------------------------------------------------------------------------------- /packages/core/PascalCase/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * PascalCase 3 | * @description Replace the snake_case or kebab-case string with PascalCase. 4 | * @example 5 | * ```ts 6 | * // Expect: "FooBarBaz" 7 | * type FooBarBaz = PascalCase<"foo_bar_baz"> 8 | * // Expect: "FooBarBaz" 9 | * type FooBarBaz = PascalCase<"foo-bar-baz"> 10 | * ``` 11 | */ 12 | // todo need support more edge cases. 13 | export type PascalCase< 14 | S extends string, 15 | sp extends string = "_" | "-" 16 | > = S extends `${infer S1}${sp}${infer S2}` 17 | ? `${Capitalize>}${Capitalize>}` 18 | : Capitalize>; 19 | -------------------------------------------------------------------------------- /docs/types/deep-mutable.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Object Operation 3 | --- 4 | 5 | # DeepMutable 6 | 7 | 8 | 9 | Make every parameter of an object - and its sub-objects recursively - mutable. 10 | 11 | ## Usage 12 | 13 | ```ts{11-17} twoslash 14 | import type { DeepMutable } from '@utype/core' 15 | 16 | type Props = { 17 | readonly x: { 18 | readonly a: 1 19 | readonly b: 'hi' 20 | }, 21 | readonly y: 'hey' 22 | } 23 | 24 | // Expect: { 25 | // x: { 26 | // a: 1, 27 | // b: 'hi' 28 | // } 29 | // y: 'hey' 30 | // } 31 | type DeepMutableProps = DeepMutable 32 | ``` 33 | -------------------------------------------------------------------------------- /docs/types/deep-readonly.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Object Operation 3 | --- 4 | 5 | # DeepReadonly 6 | 7 | 8 | 9 | Make every parameter of an object - and its sub-objects recursively - readonly. 10 | 11 | ## Usage 12 | 13 | ```ts{11-17} twoslash 14 | import type { DeepReadonly } from '@utype/core' 15 | 16 | type Props = { 17 | x: { 18 | a: 1 19 | b: 'hi' 20 | }, 21 | y: 'hey' 22 | } 23 | 24 | // Expect: { 25 | // readonly x: { 26 | // readonly a: 1, 27 | // readonly b: 'hi' 28 | // } 29 | // readonly y: 'hey' 30 | // } 31 | type DeepReadonlyProps = DeepReadonly 32 | ``` -------------------------------------------------------------------------------- /packages/core/FunctionKeys/index.d.ts: -------------------------------------------------------------------------------- 1 | import { OmitNever, NonUndefined } from "@utype/core"; 2 | 3 | /** 4 | * FunctionKeys 5 | * @description Get union type of keys that are functions in object type T. 6 | * @example 7 | * ```ts 8 | * type Prop = { 9 | * name: string; 10 | * setName: (name: string) => void; 11 | * getName: () => string; 12 | * } 13 | * // Expect: 'setName' | 'getName' 14 | * type FunctionKeysProp = FunctionKeys 15 | * ``` 16 | */ 17 | export type FunctionKeys = OmitNever< 18 | Required<{ 19 | [K in keyof T]: NonUndefined extends Function ? K : never; 20 | }> 21 | >; 22 | -------------------------------------------------------------------------------- /docs/types/deep-partial.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Object Operation 3 | alias: DeepOptional 4 | --- 5 | 6 | # DeepPartial 7 | 8 | 9 | 10 | Make every parameter of an object - and its sub-objects recursively - partial. 11 | 12 | ## Usage 13 | 14 | ```ts{11-17} twoslash 15 | import type { DeepPartial } from '@utype/core' 16 | 17 | type Props = { 18 | x: { 19 | a: 1 20 | b: 'hi' 21 | }, 22 | y: 'hey' 23 | } 24 | 25 | // Expect: { 26 | // x?: { 27 | // a?: 1, 28 | // b?: 'hi' 29 | // } 30 | // y?: 'hey' 31 | // } 32 | type DeepPartialProps = DeepPartial 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | import type { Theme } from 'vitepress' 2 | import DefaultTheme from 'vitepress/theme' 3 | import TwoslashFloatingVue from 'vitepress-plugin-twoslash/client' 4 | import type { EnhanceAppContext } from 'vitepress' 5 | 6 | import TypeInfo from './components/TypeInfo.vue' 7 | 8 | import 'vitepress-plugin-twoslash/style.css' 9 | import 'virtual:uno.css' 10 | import './styles/custom.css' 11 | 12 | export default { 13 | extends: DefaultTheme, 14 | enhanceApp({ app }: EnhanceAppContext) { 15 | app.use(TwoslashFloatingVue as any) 16 | // register global components 17 | app.component('TypeInfo', TypeInfo) 18 | } 19 | } satisfies Theme -------------------------------------------------------------------------------- /docs/.vitepress/theme/components/TypeInfo.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /docs/guide/index.md: -------------------------------------------------------------------------------- 1 | # Get Started 2 | 3 | ## Installation 4 | 5 | ::: code-group 6 | 7 | ```bash [npm] 8 | npm install @utype/core --save-dev 9 | ``` 10 | 11 | ```bash [yarn] 12 | yarn add @utype/core -D 13 | ``` 14 | 15 | ```bash [pnpm] 16 | pnpm add @utype/core -D 17 | ``` 18 | ::: 19 | 20 | ## Usage Example 21 | 22 | Simply importing the utility type you need from `@utype/core` 23 | 24 | ```ts twoslash 25 | import type { Mutable } from '@utype/core' 26 | 27 | type Props = { readonly name: string }; 28 | 29 | // Expect: { name: string } // [!code highlight] 30 | type MutableProp = Mutable 31 | ``` 32 | 33 | Refer to [type list](/types/mutable) for more details. 34 | -------------------------------------------------------------------------------- /docs/types/readonly-x.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: X Series 3 | alias: ReadonlyByKeys 4 | --- 5 | 6 | # ReadonlyX 7 | 8 | 9 | 10 | Constructs a type by setting the properties specified by `K`(string literal or union of string literals) to readonly from `T`. 11 | 12 | ## Usage 13 | 14 | ```ts twoslash 15 | import type { ReadonlyX } from '@utype/core' 16 | 17 | type Props = { 18 | name: string; 19 | age: number; 20 | visible: boolean; 21 | } 22 | 23 | // Expect: { readonly name: string; readonly age: number; visible: boolean; } // [!code highlight] 24 | type ReadonlyXProps = ReadonlyX 25 | ``` 26 | -------------------------------------------------------------------------------- /docs/types/to-maybe-ref-or-getters-for-non-function.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Reactive 3 | --- 4 | 5 | # ToMaybeRefOrGettersForNonFunction 6 | 7 | 8 | 9 | Mark the non-function property type of the object as [MaybeRefOrGetters](https://vuejs.org/api/utility-types.html#maybereforgetter). 10 | 11 | ## Usage 12 | 13 | ```ts twoslash 14 | import type { ToMaybeRefOrGettersForNonFunction } from "@utype/vue"; 15 | 16 | type Prop = { 17 | name: string; 18 | getName: () => string; 19 | }; 20 | // Expect: { name: MaybeRefOrGetters; getName: () => string; } // [!code highlight] 21 | type MyProp = ToMaybeRefOrGettersForNonFunction; 22 | ``` 23 | -------------------------------------------------------------------------------- /packages/core/UnionToIntersection/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { UnionToIntersection } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case = { name: string } | { age: number } | { visible: boolean }; 5 | type UnionToIntersectionCase = { name: string } & { age: number } & { 6 | visible: boolean; 7 | }; 8 | 9 | type cases = [ 10 | Expect, UnionToIntersectionCase>>, 11 | Expect, "foo" & 42 & true>>, 12 | Expect< 13 | Equal< 14 | UnionToIntersection<(() => "foo") | ((i: 42) => true)>, 15 | (() => "foo") & ((i: 42) => true) 16 | > 17 | > 18 | ]; 19 | -------------------------------------------------------------------------------- /packages/vue/ToMaybeRefOrGetters/index.d.ts: -------------------------------------------------------------------------------- 1 | import { NonUndefined } from '@utype/core' 2 | import type { MaybeRefOrGetter } from 'vue' 3 | 4 | /** 5 | * ToMaybeRefOrGetters 6 | * @description Mark the object's property type as [MaybeRefOrGetters](https://vuejs.org/api/utility-types.html#maybereforgetter) 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * name: string; 11 | * age: number; 12 | * } 13 | * // Expect: { name: MaybeRefOrGetters; age: MaybeRefOrGetters; } 14 | * type MyProp = ToMaybeRefOrGetters 15 | * ``` 16 | */ 17 | export type ToMaybeRefOrGetters = { 18 | [P in keyof T]?: MaybeRefOrGetter> 19 | } 20 | -------------------------------------------------------------------------------- /docs/types/mutable-x.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: X Series 3 | alias: MutableByKeys 4 | --- 5 | 6 | # MutableX 7 | 8 | 9 | 10 | Constructs a type by setting the properties specified by `K`(string literal or union of string literals) to mutable from `T`. 11 | 12 | ## Usage 13 | 14 | ```ts twoslash 15 | import type { MutableX } from '@utype/core' 16 | 17 | type Props = { 18 | readonly name: string; 19 | readonly age: number; 20 | readonly visible: boolean; 21 | } 22 | 23 | // Expect: { name: string; age: number; readonly visible: boolean; } // [!code highlight] 24 | type MutableXProps = MutableX 25 | ``` 26 | -------------------------------------------------------------------------------- /docs/types/omit-by-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Generate Object 3 | alias: OmitByValue 4 | --- 5 | 6 | # OmitByType 7 | 8 | 9 | 10 | From T remove a set of properties by value matching ValueType. 11 | 12 | ## Usage 13 | 14 | ```ts{9,11} twoslash 15 | import type { OmitByType } from '@utype/core' 16 | 17 | type Props = { 18 | foo: number; 19 | bar: number | undefined; 20 | faz: boolean; 21 | } 22 | 23 | // Expect: { bar: number | undefined; faz: boolean; } 24 | type OmitByTypeProps1 = OmitByType 25 | // Expect: { faz: boolean; } 26 | type OmitByTypeProps2 = OmitByType 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/types/pick-by-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Generate Object 3 | alias: PickByValue 4 | --- 5 | 6 | # PickByType 7 | 8 | 9 | 10 | From T pick a set of properties by value matching ValueType. 11 | 12 | ## Usage 13 | 14 | ```ts{9,11} twoslash 15 | import type { PickByType } from '@utype/core' 16 | 17 | type Props = { 18 | foo: number; 19 | bar: number | undefined; 20 | faz: boolean; 21 | } 22 | 23 | // Expect: { foo: number; } 24 | type PickByTypeProps1 = PickByType 25 | // Expect: { foo: number; bar: number | undefined; } 26 | type PickByTypeProps2 = PickByType 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/types/deep-readonly-x.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: X Series 3 | alias: DeepReadonlyByKeys 4 | --- 5 | 6 | # DeepReadonlyX 7 | 8 | 9 | 10 | Make specified properties in the object readonly, regardless of how deeply nested they are. 11 | 12 | ## Usage 13 | 14 | ```ts{10-16} twoslash 15 | import type { DeepReadonlyX } from '@utype/core' 16 | 17 | type Props = { 18 | x: { 19 | a: 1 20 | b: 'hi' 21 | }, 22 | y: 'hey' 23 | } 24 | // Expect: { 25 | // x: { 26 | // a: 1, 27 | // readonly b: 'hi' 28 | // } 29 | // readonly y: 'hey' 30 | // } 31 | type DeepReadonlyXProps = DeepReadonlyX 32 | ``` 33 | -------------------------------------------------------------------------------- /packages/core/OmitNever/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Duplicate } from "@utype/shared"; 2 | 3 | /** 4 | * OmitNever 5 | * @description Get Union type of object property types, but filtered out never types. 6 | * @example 7 | * ```ts 8 | * type Prop = { 9 | * name: string; 10 | * age: never; 11 | * visible: boolean; 12 | * } 13 | * // Expect: string | boolean 14 | * type OmitNeverProp = OmitNever 15 | * ``` 16 | */ 17 | export type OmitNever = Duplicate[keyof T]; 18 | 19 | // compatible 20 | 21 | /** 22 | * NonNeverX 23 | * @deprecated Not supported anymore; Please use OmitNever instead. 24 | */ 25 | export type NonNeverX = OmitNever; 26 | -------------------------------------------------------------------------------- /packages/core/PickByRequired/index.d.ts: -------------------------------------------------------------------------------- 1 | import { RequiredKeys } from "@utype/core"; 2 | 3 | /** 4 | * PickByRequired 5 | * @description From T pick all required properties to generate a new object type. 6 | * @alias GetRequired 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * foo: number; 11 | * bar?: string; 12 | * } 13 | * // Expect: { foo: number; } 14 | * type PickByRequiredProp = PickByRequired 15 | * ``` 16 | */ 17 | export type PickByRequired = Pick>; 18 | 19 | // alias 20 | 21 | /** 22 | * GetRequired 23 | * @description Alias for PickByRequired 24 | */ 25 | export type GetRequired = PickByRequired; 26 | -------------------------------------------------------------------------------- /docs/types/omit-by-type-fuzzy.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Generate Object 3 | alias: OmitByValueFuzzy 4 | --- 5 | 6 | # OmitByTypeFuzzy 7 | 8 | 9 | 10 | From T remove a set of properties by value fuzzy matching ValueType. 11 | 12 | ## Usage 13 | 14 | ```ts{9,11} twoslash 15 | import type { OmitByTypeFuzzy } from '@utype/core' 16 | 17 | type Props = { 18 | foo: number; 19 | bar?: number; 20 | faz: boolean; 21 | } 22 | 23 | // Expect: { foo: number; faz: boolean } 24 | type OmitByTypeFuzzyProps1 = OmitByTypeFuzzy 25 | // Expect: { foo: number } 26 | type OmitByTypeFuzzyProps2 = OmitByTypeFuzzy 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/types/pick-by-type-exact.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Generate Object 3 | alias: PickByValueExact 4 | --- 5 | 6 | # PickByTypeExact 7 | 8 | 9 | 10 | From T pick a set of properties by value matching exact ValueType. 11 | 12 | ## Usage 13 | 14 | ```ts{9,11} twoslash 15 | import type { PickByTypeExact } from '@utype/core' 16 | 17 | type Props = { 18 | foo: number; 19 | bar: number | undefined; 20 | faz: string; 21 | } 22 | 23 | // Expect: { foo: number; } 24 | type PickByTypeExactProps1 = PickByTypeExact 25 | // Expect: { bar: number | undefined; } 26 | type PickByTypeExactProps2 = PickByTypeExact 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/types/pick-by-type-fuzzy.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Generate Object 3 | alias: PickByValueFuzzy 4 | --- 5 | 6 | # PickByTypeFuzzy 7 | 8 | 9 | 10 | From T pick a set of properties by value fuzzy matching ValueType. 11 | 12 | ## Usage 13 | 14 | ```ts{9,11} twoslash 15 | import type { PickByTypeFuzzy } from '@utype/core' 16 | 17 | type Props = { 18 | foo: number; 19 | bar?: number; 20 | faz: boolean; 21 | } 22 | 23 | // Expect: { bar?: number; } 24 | type PickByTypeFuzzyProps1 = PickByTypeFuzzy 25 | // Expect: { bar?: number; faz: boolean; } 26 | type PickByTypeFuzzyProps2 = PickByTypeFuzzy 27 | ``` 28 | -------------------------------------------------------------------------------- /packages/core/DeepKeys/index.d.ts: -------------------------------------------------------------------------------- 1 | import { NonUndefined, OmitNever } from "@utype/core"; 2 | import { Keys } from "@utype/shared"; 3 | 4 | /** 5 | * DeepKeys 6 | * @description Get the union type composed of all keys from nested objects. 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * a: string; 11 | * b: number; 12 | * c: { 13 | * d: { 14 | * e: string; 15 | * } 16 | * } 17 | * } 18 | * // Expect: 'a' | 'b' | 'c' | 'd' | 'e' 19 | * type DeepKeysProp = DeepKeys 20 | * ``` 21 | */ 22 | export type DeepKeys = T extends object 23 | ? NonUndefined< 24 | OmitNever<{ [K in Keys]: `${K & string}` | DeepKeys }> 25 | > 26 | : never; 27 | -------------------------------------------------------------------------------- /docs/types/partial-x.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: X Series 3 | alias: PartialByKeys 4 | --- 5 | 6 | # PartialX 7 | 8 | 9 | 10 | Constructs a type by setting the properties specified by `K`(string literal or union of string literals) to partial from `T`. 11 | 12 | ## Usage 13 | 14 | ```ts twoslash 15 | import type { PartialX } from '@utype/core' 16 | 17 | type Props = { 18 | name: string; 19 | age: number; 20 | visible: boolean; 21 | } 22 | 23 | // Expect: { name?: string; age?: number; visible: boolean; } // [!code highlight] 24 | type PartialXProps = PartialX 25 | // @ts-expect-error 26 | type Error = PartialX // [!code error] 27 | ``` 28 | -------------------------------------------------------------------------------- /packages/core/PickByRequired/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { PickByRequired } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | foo: number; 6 | bar?: string; 7 | }; 8 | type PickByTypeCase1 = { foo: number }; 9 | 10 | type Case2 = { 11 | foo: undefined; 12 | bar?: undefined; 13 | }; 14 | type PickByTypeCase2 = { foo: undefined; }; 15 | 16 | type Case3 = { 17 | foo?: number; 18 | bar?: number | undefined; 19 | faz?: boolean; 20 | }; 21 | type PickByTypeCase3 = {}; 22 | 23 | type cases = [ 24 | Expect, PickByTypeCase1>>, 25 | Expect, PickByTypeCase2>>, 26 | Expect, PickByTypeCase3>> 27 | ]; 28 | -------------------------------------------------------------------------------- /docs/types/required-x.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: X Series 3 | alias: RequiredByKeys 4 | --- 5 | 6 | # PartialX 7 | 8 | 9 | 10 | Constructs a type by setting the properties specified by `K`(string literal or union of string literals) to required from `T`. 11 | 12 | ## Usage 13 | 14 | ```ts twoslash 15 | import type { RequiredX } from '@utype/core' 16 | 17 | type Props = { 18 | name?: string; 19 | age?: number; 20 | visible?: boolean; 21 | } 22 | 23 | // Expect: { name: string; age: number; visible?: boolean; } // [!code highlight] 24 | type RequiredXProps = RequiredX 25 | // @ts-expect-error 26 | type Error = RequiredX // [!code error] 27 | ``` 28 | -------------------------------------------------------------------------------- /packages/core/ObjectKeys/index.d.ts: -------------------------------------------------------------------------------- 1 | import { OmitNever, NonUndefined } from "@utype/core"; 2 | import { ObjectKeyType } from "@utype/shared"; 3 | 4 | /** 5 | * ObjectKeys 6 | * @description Get union type of keys that are object in object type T. 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * name: string; 11 | * breakfast: { foods: string[]; }; 12 | * dinner: { foods: string[]; }; 13 | * } 14 | * // Expect: 'breakfast' | 'dinner' 15 | * type ObjectKeysProp = ObjectKeys 16 | * ``` 17 | */ 18 | export type ObjectKeys = NonUndefined< 19 | OmitNever<{ 20 | [K in keyof T]: NonUndefined extends Record 21 | ? K 22 | : never; 23 | }> 24 | >; 25 | -------------------------------------------------------------------------------- /packages/core/RequiredKeys/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Equal } from "@utype/shared"; 2 | import { OmitNever, NonUndefined } from "@utype/core"; 3 | 4 | /** 5 | * RequiredKeys 6 | * @description Get union type of keys that are required in object type T. 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * name: string; 11 | * age: number; 12 | * visible?: boolean; 13 | * } 14 | * // Expect: 'name' | 'age' 15 | * type RequiredKeysProp = RequiredKeys 16 | * ``` 17 | */ 18 | export type RequiredKeys< 19 | T extends object, 20 | R extends Record = Required 21 | > = NonUndefined< 22 | OmitNever<{ 23 | [K in keyof T]: Equal, Pick> extends true ? K : never; 24 | }> 25 | >; 26 | -------------------------------------------------------------------------------- /packages/shared/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@utype/shared", 3 | "version": "0.1.4", 4 | "description": "Collection of typescript utility types that extends the official utility types", 5 | "author": "wzc520pyfm", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/wzc520pyfm/utype.git", 10 | "directory": "packages/shared" 11 | }, 12 | "scripts": { 13 | "ts-check": "tsc --noEmit" 14 | }, 15 | "keywords": [ 16 | "utility", 17 | "typescript", 18 | "types", 19 | "utility types" 20 | ], 21 | "exports": { 22 | ".": { 23 | "types": "./index.d.ts" 24 | }, 25 | "./*": "./*" 26 | }, 27 | "types": "./index.d.ts", 28 | "main": "" 29 | } 30 | -------------------------------------------------------------------------------- /docs/types/omit-by-type-exact.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Generate Object 3 | alias: OmitByValueExact 4 | --- 5 | 6 | # OmitByTypeExact 7 | 8 | 9 | 10 | From T remove a set of properties by value matching exact ValueType. 11 | 12 | ## Usage 13 | 14 | ```ts{9,11} twoslash 15 | import type { OmitByTypeExact } from '@utype/core' 16 | 17 | type Props = { 18 | foo: number; 19 | bar: number | undefined; 20 | faz: boolean; 21 | } 22 | 23 | // Expect: { bar: number | undefined; faz: boolean; } 24 | type OmitByTypeExactProps1 = OmitByTypeExact 25 | // Expect: { foo: number; faz: boolean; } 26 | type OmitByTypeExactProps2 = OmitByTypeExact 27 | ``` 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@utype/monorepo", 3 | "type": "module", 4 | "version": "0.1.4", 5 | "private": true, 6 | "description": "Collection of typescript utility types that extends the official utility types and also includes extensions to framework (Vue, React) types.", 7 | "scripts": { 8 | "ts-check": "tsc --noEmit", 9 | "docs:dev": "pnpm run -C docs dev", 10 | "docs:build": "pnpm run -C docs build" 11 | }, 12 | "keywords": [ 13 | "utility", 14 | "typescript", 15 | "types", 16 | "utility types" 17 | ], 18 | "author": "wzc520pyfm", 19 | "license": "MIT", 20 | "devDependencies": { 21 | "typescript": "^5.3.3" 22 | }, 23 | "engines": { 24 | "node": ">=18", 25 | "pnpm": ">=8" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /docs/types/union-to-intersection.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Generate Object 3 | alias: Union2Intersection UToI U2I 4 | --- 5 | 6 | # UnionToIntersection 7 | 8 | 9 | 10 | Get intersection type given union type U. 11 | 12 | ## Usage 13 | 14 | ```ts twoslash 15 | import type { UnionToIntersection } from '@utype/core' 16 | 17 | type Props = { name: string } | { age: number } | { visible: boolean } 18 | 19 | // Expect: { name: string } & { age: number } & { visible: boolean } // [!code highlight] 20 | type UnionToIntersectionProps = UnionToIntersection 21 | 22 | // Expect: 'foo' & 42 & true // [!code highlight] 23 | type Case = UnionToIntersection<'foo' | 42 | true> 24 | ``` 25 | -------------------------------------------------------------------------------- /packages/core/ReadonlyKeys/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Equal } from "@utype/shared"; 2 | import { OmitNever, NonUndefined } from "@utype/core"; 3 | 4 | /** 5 | * ReadonlyKeys 6 | * @description Get union type of keys that are readonly in object type T. 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * readonly name: string; 11 | * readonly age: number; 12 | * visible: boolean; 13 | * } 14 | * // Expect: 'name' | 'age' 15 | * type ReadonlyKeysProp = ReadonlyKeys 16 | * ``` 17 | */ 18 | export type ReadonlyKeys< 19 | T extends object, 20 | R extends Record = Readonly 21 | > = NonUndefined< 22 | OmitNever<{ 23 | [K in keyof T]: Equal, Pick> extends true ? K : never; 24 | }> 25 | >; 26 | -------------------------------------------------------------------------------- /packages/core/CamelCase/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { CamelCase } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type cases = [ 5 | Expect, "foobar">>, 6 | Expect, "foobar">>, 7 | Expect, "fooBar">>, 8 | Expect, "fooBar">>, 9 | Expect, "fooBarHelloWorld">>, 10 | Expect, "fooBarHelloWorld">>, 11 | Expect, "helloWorldWithTypes">>, 12 | Expect, "helloWorldWithTypes">>, 13 | Expect, "">>, 14 | Expect, "😎">> 15 | ]; 16 | -------------------------------------------------------------------------------- /packages/core/MutableKeys/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Equal } from "@utype/shared"; 2 | import { Mutable, OmitNever, NonUndefined } from "@utype/core"; 3 | 4 | /** 5 | * MutableKeys 6 | * @description Get union type of keys that are mutable (not readonly) in object type T. 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * readonly name: string; 11 | * age: number; 12 | * visible: boolean; 13 | * } 14 | * // Expect: 'age' | 'visible' 15 | * type MutableKeysProp = MutableKeys 16 | * ``` 17 | */ 18 | export type MutableKeys< 19 | T extends object, 20 | R extends Record = Mutable 21 | > = NonUndefined< 22 | OmitNever<{ 23 | [K in keyof T]: Equal, Pick> extends true ? K : never; 24 | }> 25 | >; 26 | -------------------------------------------------------------------------------- /docs/.vitepress/configs/sidebar.ts: -------------------------------------------------------------------------------- 1 | import typesLocale from "../pages/types.json"; 2 | 3 | function getTypesSideBar() { 4 | return Object.entries(typesLocale).map(([_, val]) => mapPrefix(val, '/types')) 5 | } 6 | 7 | const getSidebar = () => { 8 | return { 9 | '/types/': getTypesSideBar(), 10 | } 11 | } 12 | 13 | type Item = { 14 | text: string 15 | items?: Item[] 16 | link?: string 17 | } 18 | 19 | function mapPrefix(item: Item, prefix = "") { 20 | if (item.items && item.items.length > 0) { 21 | return { 22 | ...item, 23 | items: item.items.map((child) => mapPrefix(child, prefix)), 24 | }; 25 | } 26 | return { 27 | ...item, 28 | link: `${prefix}${item.link}`, 29 | }; 30 | } 31 | 32 | export const sidebar = getSidebar() 33 | -------------------------------------------------------------------------------- /packages/core/DeepMutable/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Keys } from "@utype/shared"; 2 | 3 | /** 4 | * DeepMutable 5 | * @description Make every parameter of an object - and its sub-objects recursively - mutable. 6 | * @example 7 | * ```ts 8 | * type Prop = { 9 | * readonly x: { 10 | * readonly a: 1 11 | * readonly b: 'hi' 12 | * }, 13 | * readonly y: 'hey' 14 | * } 15 | * // Expect: { 16 | * // x: { 17 | * // a: 1, 18 | * // b: 'hi' 19 | * // } 20 | * // y: 'hey' 21 | * // } 22 | * type DeepMutableProp = DeepMutable 23 | * ``` 24 | */ 25 | export type DeepMutable = T extends Function 26 | ? T 27 | : { 28 | -readonly [K in Keys]: T[K] extends object ? DeepMutable : T[K]; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/core/DeepReadonly/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Keys } from "@utype/shared"; 2 | 3 | /** 4 | * DeepReadonly 5 | * @description Make every parameter of an object - and its sub-objects recursively - readonly. 6 | * @example 7 | * ```ts 8 | * type Prop = { 9 | * x: { 10 | * a: 1 11 | * b: 'hi' 12 | * }, 13 | * y: 'hey' 14 | * } 15 | * // Expect: { 16 | * // readonly x: { 17 | * // readonly a: 1, 18 | * // readonly b: 'hi' 19 | * // } 20 | * // readonly y: 'hey' 21 | * // } 22 | * type DeepReadonlyProp = DeepReadonly 23 | * ``` 24 | */ 25 | // todo need support arr, fun, class, etc. 26 | export type DeepReadonly = { 27 | readonly [K in Keys]: Keys extends never ? T[K] : DeepReadonly; 28 | }; 29 | -------------------------------------------------------------------------------- /docs/unocss.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | presetAttributify, 4 | presetIcons, 5 | presetUno, 6 | transformerDirectives, 7 | transformerVariantGroup, 8 | } from 'unocss' 9 | 10 | export default defineConfig({ 11 | shortcuts: { 12 | 'border-main': 'border-$vp-c-divider', 13 | 'bg-main': 'bg-gray-400', 14 | 'bg-base': 'bg-white dark:bg-hex-1a1a1a', 15 | }, 16 | presets: [ 17 | presetUno(), 18 | presetAttributify(), 19 | presetIcons({ 20 | scale: 1.2, 21 | warn: true, 22 | }), 23 | ], 24 | theme: { 25 | colors: {}, 26 | fontFamily: { 27 | mono: 'var(--vt-font-family-mono)', 28 | }, 29 | }, 30 | transformers: [ 31 | transformerDirectives(), 32 | transformerVariantGroup(), 33 | ], 34 | }) -------------------------------------------------------------------------------- /packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@utype/core", 3 | "version": "0.1.5", 4 | "description": "Collection of typescript utility types that extends the official utility types", 5 | "author": "wzc520pyfm", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/wzc520pyfm/utype.git", 10 | "directory": "packages/core" 11 | }, 12 | "scripts": { 13 | "ts-check": "tsc" 14 | }, 15 | "keywords": [ 16 | "utility", 17 | "typescript", 18 | "types", 19 | "utility types" 20 | ], 21 | "exports": { 22 | ".": { 23 | "types": "./index.d.ts" 24 | }, 25 | "./*": "./*" 26 | }, 27 | "main": "", 28 | "types": "./index.d.ts", 29 | "dependencies": { 30 | "@utype/shared": "0.1.3" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/shared/TupleHead/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * TupleHead 3 | * @description Extracting the first element of a tuple as a tuple type. 4 | * @alias FirstAsTuple 5 | * @example 6 | * ```ts 7 | * type Prop = [a: string, b: number, c: boolean] 8 | * // Expect: [a: string] 9 | * type TupleHeadProp = TupleHead 10 | * ``` 11 | */ 12 | export type TupleHead = T extends readonly [] 13 | ? never 14 | : T extends readonly [any?, ...infer R] 15 | ? T extends readonly [...infer H, ...R] 16 | ? T extends any[] 17 | ? H 18 | : readonly [...H] 19 | : never 20 | : never; 21 | 22 | // alias 23 | 24 | /** 25 | * FirstAsTuple 26 | * @description Alias for TupleHead 27 | */ 28 | export type FirstAsTuple = TupleHead; 29 | -------------------------------------------------------------------------------- /packages/vue/ToMaybeRefOrGettersForNonFunction/index.d.ts: -------------------------------------------------------------------------------- 1 | import { FunctionKeys, NonUndefined } from "@utype/core"; 2 | import { MaybeRefOrGetter } from "vue"; 3 | 4 | /** 5 | * ToMaybeRefOrGettersForNonFunction 6 | * @description Mark the non-function property type of the object as [MaybeRefOrGetters](https://vuejs.org/api/utility-types.html#maybereforgetter) 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * name: string; 11 | * getName: () => string; 12 | * } 13 | * // Expect: { name: MaybeRefOrGetters; getName: () => string; } 14 | * type MyProp = ToMaybeRefOrGettersForNonFunction 15 | * ``` 16 | */ 17 | export type ToMaybeRefOrGettersForNonFunction = { 18 | [P in keyof T]?: P extends FunctionKeys ? T[P] : MaybeRefOrGetter> 19 | } 20 | -------------------------------------------------------------------------------- /packages/core/PascalCase/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { PascalCase } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type cases = [ 5 | Expect, "Foobar">>, 6 | Expect, "Foobar">>, 7 | Expect, "Foobar">>, 8 | Expect, "FooBar">>, 9 | Expect, "FooBar">>, 10 | Expect, "FooBarHelloWorld">>, 11 | Expect, "FooBarHelloWorld">>, 12 | Expect, "HelloWorldWithTypes">>, 13 | Expect, "HelloWorldWithTypes">>, 14 | Expect, "">>, 15 | Expect, "😎">> 16 | ]; 17 | -------------------------------------------------------------------------------- /packages/core/PickByType/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { PickByType } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | foo: number; 6 | bar: number | undefined; 7 | faz: boolean; 8 | }; 9 | type PickByTypeCase1 = { foo: number }; 10 | 11 | type Case2 = { 12 | foo: number; 13 | bar: number | undefined; 14 | faz: boolean; 15 | }; 16 | type PickByTypeCase2 = { foo: number; bar: number | undefined }; 17 | 18 | type Case3 = { 19 | foo: number; 20 | bar: number | undefined; 21 | faz: boolean; 22 | }; 23 | type PickByTypeCase3 = {}; 24 | 25 | type cases = [ 26 | Expect, PickByTypeCase1>>, 27 | Expect, PickByTypeCase2>>, 28 | Expect, PickByTypeCase3>> 29 | ]; 30 | -------------------------------------------------------------------------------- /docs/types/curried.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: Function 3 | --- 4 | 5 | # Curried 6 | 7 | 8 | 9 | [Currying](https://en.wikipedia.org/wiki/Currying) function with support for dynamic parameters. 10 | 11 | ## Usage 12 | 13 | ```ts{13-15} twoslash 14 | import type { Curried } from '@utype/core' 15 | 16 | // Your implementation logic... 17 | declare function yourCurrying(fn: (...args: A) => R): Curried 18 | 19 | const yourFun = (a: string, b: number) => true; 20 | const curriedYourFun = yourCurrying(yourFun); 21 | 22 | // use your curried func 23 | const res1 = curriedYourFun('123', 123); 24 | const res2 = curriedYourFun('123')(123); 25 | 26 | // Expect: 27 | // ((a: string, b: number) => boolean) & 28 | // ((a: string) => (b: number) => boolean) 29 | type CurriedYourFun = typeof curriedYourFun; 30 | ``` 31 | -------------------------------------------------------------------------------- /packages/core/PartialX/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Keys, Duplicate } from "@utype/shared"; 2 | 3 | /** 4 | * PartialX 5 | * @description Constructs a type by setting the properties specified by `K`(string literal or union of string literals) to partial from `T`. 6 | * @alias PartialByKeys 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * name: string; 11 | * age: number; 12 | * visible: boolean; 13 | * } 14 | * // Expect: { name?: string; age?: number; visible: boolean; } 15 | * type PartialXProp = PartialX 16 | * ``` 17 | */ 18 | export type PartialX = Keys> = Duplicate< 19 | Partial> & Omit 20 | >; 21 | 22 | // alias 23 | 24 | /** 25 | * PartialByKeys 26 | * @description Alias for PartialX 27 | */ 28 | export type PartialByKeys = Keys> = PartialX; 29 | -------------------------------------------------------------------------------- /packages/shared/utils/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './helper' 2 | 3 | /** 4 | * Expect 5 | * @description Only accept the 'true' type, typically used to determine if the result returned by 'Equal' is true. 6 | * @example 7 | * // ts-expect-error 8 | * type Case = Expect 9 | * // ts-expect-error 10 | * type Case = Expect> 11 | * // Expect 12 | * type Case = Expect> 13 | */ 14 | export type Expect = T 15 | 16 | /** 17 | * Equal 18 | * @description Compare whether two types are equal. 19 | * @example 20 | * ```ts 21 | * // Expect: false 22 | * type Case = Equal 23 | * ``` 24 | */ 25 | export type Equal = 26 | (() => T extends X ? 1 : 2) extends 27 | (() => T extends Y ? 1 : 2) ? true : false 28 | export type NotEqual = true extends Equal ? false : true 29 | -------------------------------------------------------------------------------- /packages/core/RequiredX/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Duplicate } from "@utype/shared"; 2 | 3 | /** 4 | * RequiredX 5 | * @description Constructs a type by setting the properties specified by `K`(string literal or union of string literals) to required from `T`. 6 | * @alias RequiredByKeys 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * name?: string; 11 | * age?: number; 12 | * visible?: boolean; 13 | * } 14 | * // Expect: { name: string; age: number; visible?: boolean; } 15 | * type RequiredXProp = RequiredX 16 | * ``` 17 | */ 18 | export type RequiredX = Duplicate< 19 | Required> & Omit 20 | >; 21 | 22 | // alias 23 | 24 | /** 25 | * RequiredByKeys 26 | * @description Alias for RequiredX 27 | */ 28 | export type RequiredByKeys = RequiredX; 29 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@utype/docs", 3 | "version": "0.1.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "vitepress dev", 9 | "build": "vitepress build", 10 | "preview": "vitepress preview" 11 | }, 12 | "keywords": [ 13 | "utility", 14 | "typescript", 15 | "types", 16 | "utility types" 17 | ], 18 | "author": "wzc520pyfm", 19 | "license": "MIT", 20 | "devDependencies": { 21 | "@utype/core": "workspace:^", 22 | "@utype/react": "workspace:^", 23 | "@utype/shared": "workspace:^", 24 | "@utype/vue": "workspace:^", 25 | "unocss": "^0.58.5", 26 | "vite": "^5.1.5", 27 | "vitepress": "1.0.0-rc.40", 28 | "vitepress-plugin-twoslash": "^0.10.2" 29 | }, 30 | "dependencies": { 31 | "vue": "^3.4.21" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/core/PickByTypeExact/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { PickByTypeExact } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | foo: number; 6 | bar: number | undefined; 7 | faz: boolean; 8 | }; 9 | type PickByTypeExactCase1 = { foo: number }; 10 | 11 | type Case2 = { 12 | foo: number; 13 | bar: number | undefined; 14 | faz: boolean; 15 | }; 16 | type PickByTypeExactCase2 = { bar: number | undefined }; 17 | 18 | type Case3 = { 19 | foo: number; 20 | bar: number | undefined; 21 | faz: boolean; 22 | }; 23 | type PickByTypeExactCase3 = {}; 24 | 25 | type cases = [ 26 | Expect, PickByTypeExactCase1>>, 27 | Expect< 28 | Equal, PickByTypeExactCase2> 29 | >, 30 | Expect, PickByTypeExactCase3>> 31 | ]; 32 | -------------------------------------------------------------------------------- /packages/core/ReadonlyX/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { ReadonlyX } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | name: string; 6 | age: number; 7 | }; 8 | type ReadonlyXCase1 = { 9 | readonly name: string; 10 | readonly age: number; 11 | }; 12 | 13 | type Case2 = { 14 | name: string; 15 | age: number; 16 | }; 17 | type ReadonlyXCase2 = { 18 | readonly name: string; 19 | age: number; 20 | }; 21 | 22 | type Case3 = { 23 | name: string; 24 | age: number; 25 | visible: boolean; 26 | }; 27 | type ReadonlyXCase3 = { 28 | readonly name: string; 29 | readonly age: number; 30 | visible: boolean; 31 | }; 32 | 33 | type cases = [ 34 | Expect, ReadonlyXCase1>>, 35 | Expect, ReadonlyXCase2>>, 36 | Expect, ReadonlyXCase3>> 37 | ]; 38 | -------------------------------------------------------------------------------- /packages/core/ReadonlyX/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Duplicate } from "@utype/shared"; 2 | 3 | /** 4 | * ReadonlyX 5 | * @description Constructs a type by setting the properties specified by `K`(string literal or union of string literals) to readonly from `T`. 6 | * @alias ReadonlyByKeys 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * name: string; 11 | * age: number; 12 | * visible: boolean; 13 | * } 14 | * // Expect: { readonly name: string; readonly age: number; visible: boolean; } 15 | * type ReadonlyXProp = ReadonlyX 16 | * ``` 17 | */ 18 | export type ReadonlyX = Duplicate< 19 | Readonly> & Omit 20 | >; 21 | 22 | // alias 23 | 24 | /** 25 | * ReadonlyByKeys 26 | * @description Alias for ReadonlyX 27 | */ 28 | export type ReadonlyByKeys = ReadonlyX; 29 | -------------------------------------------------------------------------------- /packages/core/DeepPartial/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Keys, OnlyObject } from "@utype/shared"; 2 | 3 | /** 4 | * DeepPartial 5 | * @description Make every parameter of an object - and its sub-objects recursively - partial. 6 | * @alias DeepOptional 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * x: { 11 | * a: 1 12 | * b: 'hi' 13 | * }, 14 | * y: 'hey' 15 | * } 16 | * // Expect: { 17 | * // x?: { 18 | * // a?: 1, 19 | * // b?: 'hi' 20 | * // } 21 | * // y?: 'hey' 22 | * // } 23 | * type DeepPartialProp = DeepPartial 24 | * ``` 25 | */ 26 | // todo need support array 27 | export type DeepPartial = { 28 | [K in Keys]?: T[K] extends OnlyObject ? DeepPartial : T[K]; 29 | }; 30 | 31 | // alias 32 | 33 | /** 34 | * DeepOptional 35 | * @description Alias for PartialKeys 36 | */ 37 | export type DeepOptional = DeepPartial; 38 | -------------------------------------------------------------------------------- /packages/core/OmitByType/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { OmitByType } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | foo: number; 6 | bar: number | undefined; 7 | faz: boolean; 8 | }; 9 | type OmitByTypeCase1 = { bar: number | undefined; faz: boolean }; 10 | 11 | type Case2 = { 12 | foo: number; 13 | bar: number | undefined; 14 | faz: boolean; 15 | }; 16 | type OmitByTypeCase2 = { faz: boolean }; 17 | 18 | type Case3 = { 19 | foo: number; 20 | bar: number | undefined; 21 | faz: boolean; 22 | }; 23 | type OmitByTypeCase3 = { 24 | foo: number; 25 | bar: number | undefined; 26 | faz: boolean; 27 | }; 28 | 29 | type cases = [ 30 | Expect, OmitByTypeCase1>>, 31 | Expect, OmitByTypeCase2>>, 32 | Expect, OmitByTypeCase3>> 33 | ]; 34 | -------------------------------------------------------------------------------- /packages/shared/RecordToUnion/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * RecordToUnion 3 | * @description Get union type given record type U. 4 | * @alias Record2Union RToU R2U 5 | * @example 6 | * ```ts 7 | * type Prop = { name: string; visible: boolean; } 8 | * // Expect: string | boolean 9 | * type RecordToUnionProp = RecordToUnion 10 | * ``` 11 | */ 12 | export type RecordToUnion> = T[keyof T] 13 | 14 | // alias 15 | 16 | /** 17 | * Record2Union 18 | * @description Alias for RecordToUnion 19 | */ 20 | export type Record2Union> = RecordToUnion; 21 | 22 | /** 23 | * RToU 24 | * @description Alias for RecordToUnion 25 | */ 26 | export type RToU> = RecordToUnion; 27 | 28 | /** 29 | * R2U 30 | * @description Alias for RecordToUnion 31 | */ 32 | export type R2U> = RecordToUnion; 33 | -------------------------------------------------------------------------------- /packages/core/MutableX/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { MutableX } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | readonly name: string; 6 | readonly age: number; 7 | }; 8 | type MutableXCase1 = { 9 | name: string; 10 | age: number; 11 | }; 12 | 13 | type Case2 = { 14 | readonly name: string; 15 | readonly age: number; 16 | }; 17 | type MutableXCase2 = { 18 | name: string; 19 | readonly age: number; 20 | }; 21 | 22 | type Case3 = { 23 | readonly name: string; 24 | readonly age: number; 25 | readonly visible: boolean; 26 | }; 27 | type MutableXCase3 = { 28 | name: string; 29 | age: number; 30 | readonly visible: boolean; 31 | }; 32 | 33 | type cases = [ 34 | Expect, MutableXCase1>>, 35 | Expect, MutableXCase2>>, 36 | Expect, MutableXCase3>> 37 | ]; 38 | -------------------------------------------------------------------------------- /packages/core/OmitByTypeFuzzy/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { OmitByTypeFuzzy } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | foo: number; 6 | bar: number | undefined; 7 | faz: boolean; 8 | }; 9 | type OmitByTypeFuzzyCase1 = { faz: boolean }; 10 | 11 | type Case2 = { 12 | foo: number; 13 | bar: number | undefined; 14 | faz: boolean; 15 | }; 16 | type OmitByTypeFuzzyCase2 = { foo: number }; 17 | 18 | type Case3 = { 19 | foo: number; 20 | bar?: number; 21 | faz: boolean; 22 | }; 23 | type OmitByTypeFuzzyCase3 = { 24 | foo: number; 25 | faz: boolean; 26 | }; 27 | 28 | type cases = [ 29 | Expect, OmitByTypeFuzzyCase1>>, 30 | Expect< 31 | Equal, OmitByTypeFuzzyCase2> 32 | >, 33 | Expect, OmitByTypeFuzzyCase3>> 34 | ]; 35 | -------------------------------------------------------------------------------- /packages/core/PartialX/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { PartialX } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type BaseCase = { 5 | name: string; 6 | age: number; 7 | address: string; 8 | }; 9 | 10 | type PartialXCase1 = { 11 | name?: string; 12 | age: number; 13 | address: string; 14 | }; 15 | 16 | type PartialXCase2 = { 17 | name?: string; 18 | age?: number; 19 | address: string; 20 | }; 21 | 22 | type PartialXCase3 = { 23 | name?: string; 24 | age?: number; 25 | address?: string; 26 | }; 27 | 28 | type cases = [ 29 | Expect, PartialXCase1>>, 30 | Expect, PartialXCase2>>, 31 | Expect, PartialXCase3>>, 32 | Expect, Partial>> 33 | ]; 34 | 35 | type errors = [ 36 | // @ts-expect-error 37 | PartialX 38 | ]; 39 | -------------------------------------------------------------------------------- /packages/core/PickByType/index.d.ts: -------------------------------------------------------------------------------- 1 | import { OmitNever } from "@utype/core"; 2 | 3 | /** 4 | * PickByType 5 | * @description From T pick a set of properties by value matching ValueType. 6 | * @alias PickByValue 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * foo: number; 11 | * bar: number | undefined; 12 | * faz: boolean; 13 | * } 14 | * // Expect: { foo: number; } 15 | * type PickByTypeProp1 = PickByType 16 | * // Expect: { foo: number; bar: number | undefined; } 17 | * type PickByTypeProp2 = PickByType 18 | * ``` 19 | */ 20 | export type PickByType = Pick< 21 | T, 22 | OmitNever<{ 23 | [K in keyof T]: T[K] extends ValueType ? K : never; 24 | }> 25 | >; 26 | 27 | // alias 28 | 29 | /** 30 | * PickByValue 31 | * @description Alias for PickByType 32 | */ 33 | export type PickByValue = PickByType; 34 | -------------------------------------------------------------------------------- /packages/core/PickByTypeFuzzy/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { PickByTypeFuzzy } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | foo: number; 6 | bar: number | undefined; 7 | faz: boolean; 8 | }; 9 | type PickByTypeFuzzyCase1 = { foo: number; bar: number | undefined }; 10 | 11 | type Case2 = { 12 | foo: number; 13 | bar: number | undefined; 14 | faz: boolean; 15 | }; 16 | type PickByTypeFuzzyCase2 = { foo: number; bar: number | undefined }; 17 | 18 | type Case3 = { 19 | foo: number; 20 | bar?: number; 21 | faz: boolean; 22 | }; 23 | type PickByTypeFuzzyCase3 = { bar?: number }; 24 | 25 | type cases = [ 26 | Expect, PickByTypeFuzzyCase1>>, 27 | Expect< 28 | Equal, PickByTypeFuzzyCase2> 29 | >, 30 | Expect, PickByTypeFuzzyCase3>> 31 | ]; 32 | -------------------------------------------------------------------------------- /packages/core/OmitByType/index.d.ts: -------------------------------------------------------------------------------- 1 | import { OmitNever } from "@utype/core"; 2 | 3 | /** 4 | * OmitByType 5 | * @description From T remove a set of properties by value matching ValueType. 6 | * @alias OmitByValue 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * foo: number; 11 | * bar: number | undefined; 12 | * faz: boolean; 13 | * } 14 | * // Expect: { bar: number | undefined; faz: boolean; } 15 | * type OmitByTypeProp1 = OmitByType 16 | * // Expect: { faz: boolean; } 17 | * type OmitByTypeProp2 = OmitByType 18 | * ``` 19 | */ 20 | export type OmitByType = Omit< 21 | T, 22 | OmitNever<{ 23 | [K in keyof T]: T[K] extends ValueType ? K : never; 24 | }> 25 | >; 26 | 27 | // alias 28 | 29 | /** 30 | * OmitByValue 31 | * @description Alias for OmitByType 32 | */ 33 | export type OmitByValue = OmitByType; 34 | -------------------------------------------------------------------------------- /packages/core/MutableX/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Duplicate } from "@utype/shared"; 2 | import { Mutable } from "@utype/core"; 3 | 4 | /** 5 | * MutableX 6 | * @description Constructs a type by setting the properties specified by `K`(string literal or union of string literals) to mutable from `T`. 7 | * @alias MutableByKeys 8 | * @example 9 | * ```ts 10 | * type Prop = { 11 | * readonly name: string; 12 | * readonly age: number; 13 | * readonly visible: boolean; 14 | * } 15 | * // Expect: { name: string; age: number; readonly visible: boolean; } 16 | * type MutableXProp = MutableX 17 | * ``` 18 | */ 19 | export type MutableX = Duplicate< 20 | Mutable> & Omit 21 | >; 22 | 23 | // alias 24 | 25 | /** 26 | * MutableByKeys 27 | * @description Alias for MutableX 28 | */ 29 | export type MutableByKeys = MutableX; 30 | -------------------------------------------------------------------------------- /packages/core/RequiredX/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { RequiredX } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type BaseCase = { 5 | name?: string; 6 | age?: number; 7 | address?: string; 8 | }; 9 | 10 | type RequiredXCase1 = { 11 | name: string; 12 | age?: number; 13 | address?: string; 14 | }; 15 | 16 | type RequiredXCase2 = { 17 | name: string; 18 | age: number; 19 | address?: string; 20 | }; 21 | 22 | type RequiredXCase3 = { 23 | name: string; 24 | age: number; 25 | address: string; 26 | }; 27 | 28 | type cases = [ 29 | Expect, RequiredXCase1>>, 30 | Expect, RequiredXCase2>>, 31 | Expect, RequiredXCase3>>, 32 | Expect, Required>> 33 | ]; 34 | 35 | type errors = [ 36 | // @ts-expect-error 37 | RequiredX 38 | ]; 39 | -------------------------------------------------------------------------------- /packages/core/NonFunctionKeys/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { NonFunctionKeys } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | name: string; 6 | getName: () => string; 7 | }; 8 | type NonFunctionKeysCase1 = "name"; 9 | 10 | type Case2 = { 11 | name: string; 12 | age: number; 13 | getName: () => string; 14 | setName?: (name: string) => void; 15 | }; 16 | type NonFunctionKeysCase2 = "name" | "age"; 17 | 18 | type Case3 = { 19 | name: string; 20 | age: number; 21 | getName: () => string; 22 | setName?: (name: string) => void; 23 | mapCase?: Map; 24 | }; 25 | type NonFunctionKeysCase3 = "name" | "age" | "mapCase"; 26 | 27 | type TT = NonFunctionKeys; 28 | 29 | type cases = [ 30 | Expect, NonFunctionKeysCase1>>, 31 | Expect, NonFunctionKeysCase2>>, 32 | Expect, NonFunctionKeysCase3>> 33 | ]; 34 | -------------------------------------------------------------------------------- /packages/core/PartialKeys/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Equal } from "@utype/shared"; 2 | import { OmitNever, NonUndefined } from "@utype/core"; 3 | 4 | /** 5 | * PartialKeys 6 | * @description Get union type of keys that are partial in object type T. 7 | * @alias OptionalKeys 8 | * @example 9 | * ```ts 10 | * type Prop = { 11 | * name: string; 12 | * age?: number; 13 | * visible?: boolean; 14 | * } 15 | * // Expect: 'age' | 'visible' 16 | * type PartialKeysProp = PartialKeys 17 | * ``` 18 | */ 19 | export type PartialKeys< 20 | T extends object, 21 | R extends Partial = Partial 22 | > = NonUndefined< 23 | OmitNever<{ 24 | [K in keyof T]: Equal, Pick> extends true ? K : never; 25 | }> 26 | >; 27 | 28 | // alias 29 | 30 | /** 31 | * OptionalKeys 32 | * @description Alias for PartialKeys 33 | */ 34 | export type OptionalKeys< 35 | T extends object, 36 | R extends Partial = Partial 37 | > = PartialKeys; 38 | -------------------------------------------------------------------------------- /packages/core/OmitByTypeExact/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { OmitByTypeExact } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | foo: number; 6 | bar: number | undefined; 7 | faz: boolean; 8 | }; 9 | type OmitByTypeExactCase1 = { bar: number | undefined; faz: boolean }; 10 | 11 | type Case2 = { 12 | foo: number; 13 | bar: number | undefined; 14 | faz: boolean; 15 | }; 16 | type OmitByTypeExactCase2 = { foo: number; faz: boolean }; 17 | 18 | type Case3 = { 19 | foo: number; 20 | bar: number | undefined; 21 | faz: boolean; 22 | }; 23 | type OmitByTypeExactCase3 = { 24 | foo: number; 25 | bar: number | undefined; 26 | faz: boolean; 27 | }; 28 | 29 | type cases = [ 30 | Expect, OmitByTypeExactCase1>>, 31 | Expect< 32 | Equal, OmitByTypeExactCase2> 33 | >, 34 | Expect, OmitByTypeExactCase3>> 35 | ]; 36 | -------------------------------------------------------------------------------- /packages/core/OmitByTypeFuzzy/index.d.ts: -------------------------------------------------------------------------------- 1 | import { OmitNever } from "@utype/core"; 2 | 3 | /** 4 | * OmitByTypeFuzzy 5 | * @description From T remove a set of properties by value fuzzy matching ValueType. 6 | * @alias OmitByValueFuzzy 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * foo: number; 11 | * bar?: number; 12 | * faz: boolean; 13 | * } 14 | * // Expect: { foo: number; faz: boolean } 15 | * type OmitByTypeFuzzyProp1 = OmitByTypeFuzzy 16 | * // Expect: { foo: number } 17 | * type OmitByTypeFuzzyProp2 = OmitByTypeFuzzy 18 | * ``` 19 | */ 20 | export type OmitByTypeFuzzy = Omit< 21 | T, 22 | OmitNever<{ 23 | [K in keyof T]: Extract extends never ? never : K; 24 | }> 25 | >; 26 | 27 | // alias 28 | 29 | /** 30 | * OmitByValueFuzzy 31 | * @description Alias for OmitByTypeFuzzy 32 | */ 33 | export type OmitByValueFuzzy = OmitByTypeFuzzy; 34 | -------------------------------------------------------------------------------- /packages/core/PickByTypeFuzzy/index.d.ts: -------------------------------------------------------------------------------- 1 | import { OmitNever } from "@utype/core"; 2 | 3 | /** 4 | * PickByTypeFuzzy 5 | * @description From T pick a set of properties by value fuzzy matching ValueType. 6 | * @alias PickByValueFuzzy 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * foo: number; 11 | * bar?: number; 12 | * faz: boolean; 13 | * } 14 | * // Expect: { bar?: number; } 15 | * type PickByTypeFuzzyProp1 = PickByTypeFuzzy 16 | * // Expect: { bar?: number; faz: boolean; } 17 | * type PickByTypeFuzzyProp2 = PickByTypeFuzzy 18 | * ``` 19 | */ 20 | export type PickByTypeFuzzy = Pick< 21 | T, 22 | OmitNever<{ 23 | [K in keyof T]: Extract extends never ? never : K; 24 | }> 25 | >; 26 | 27 | // alias 28 | 29 | /** 30 | * PickByValueFuzzy 31 | * @description Alias for PickByTypeFuzzy 32 | */ 33 | export type PickByValueFuzzy = PickByTypeFuzzy; 34 | -------------------------------------------------------------------------------- /docs/.vitepress/config.mts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitepress' 2 | import { transformerTwoslash } from 'vitepress-plugin-twoslash' 3 | import { sidebar } from './configs' 4 | 5 | // https://vitepress.dev/reference/site-config 6 | export default defineConfig({ 7 | title: "UType", 8 | description: "Collection of TS Utility Types", 9 | head: [['link', { rel: 'icon', href: '/favicon.ico' }]], 10 | markdown: { 11 | codeTransformers: [ 12 | transformerTwoslash() as any 13 | ] 14 | }, 15 | themeConfig: { 16 | // https://vitepress.dev/reference/default-theme-config 17 | logo: '/logo.svg', 18 | nav: [ 19 | { 20 | text: 'Guide', 21 | items: [ 22 | { text: 'Get Started', link: '/guide/' }, 23 | ] 24 | }, 25 | { text: 'Utility Types', link: '/types/mutable' } 26 | ], 27 | 28 | sidebar, 29 | 30 | socialLinks: [ 31 | { icon: 'github', link: 'https://github.com/wzc520pyfm/utype' } 32 | ] 33 | } 34 | }) 35 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | # https://vitepress.dev/reference/default-theme-home-page 3 | layout: home 4 | 5 | hero: 6 | name: "UType" 7 | # text: "More TS Utility Types" 8 | text: "Collection of TS Utility Types" 9 | tagline: Collection of typescript utility types that extends the official utility types. 10 | image: /logo.svg 11 | actions: 12 | - theme: brand 13 | text: Get Started 14 | link: /guide/ 15 | - theme: alt 16 | text: Utility Types 17 | link: /types/mutable 18 | # - theme: alt 19 | # text: Add-ons 20 | # link: /api-examples 21 | - theme: alt 22 | text: View on GitHub 23 | link: https://github.com/wzc520pyfm/utype 24 | 25 | features: 26 | - title: Feature Rich 27 | icon: 🚀 28 | details: 50+ Utility Types for you to choose from 29 | - title: Consistent 30 | icon: 🔋 31 | details: Still Continuously Adding Types 32 | - title: Type Strong 33 | icon: 💪 34 | details: Pure TypeScript 35 | --- 36 | 37 | -------------------------------------------------------------------------------- /packages/core/DeepRequired/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Keys, OnlyObject } from "@utype/shared"; 2 | import { NonUndefined } from "@utype/core"; 3 | 4 | /** 5 | * DeepRequired 6 | * @description Make every parameter of an object - and its sub-objects recursively - required. 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * x: { 11 | * a?: 1 12 | * b: 'hi' 13 | * }, 14 | * y?: 'hey' 15 | * } 16 | * // Expect: { 17 | * // x: { 18 | * // a: 1, 19 | * // b: 'hi' 20 | * // } 21 | * // y: 'hey' 22 | * // } 23 | * type DeepRequiredProp = DeepRequired 24 | * ``` 25 | */ 26 | // todo need support array 27 | export type DeepRequired = T extends OnlyObject 28 | ? _DeepRequiredObject 29 | : T; 30 | 31 | /** @private */ 32 | export interface _DeepRequiredArray 33 | extends Array>> {} 34 | 35 | /** @private */ 36 | export type _DeepRequiredObject = { 37 | [P in Keys]-?: DeepRequired>; 38 | }; 39 | -------------------------------------------------------------------------------- /packages/core/MergeAll/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { MergeAll, MergeLeftAll, MergeRightAll } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1Foo = { a: 1; b: 2 }; 5 | type Case1Bar = { a: 2 }; 6 | type Case1Baz = { c: 3 }; 7 | type MergeAllCase1 = { 8 | a: 1 | 2; 9 | b: 2; 10 | c: 3; 11 | }; 12 | 13 | type Case2Foo = { a: 1; b: 2 }; 14 | type Case2Bar = { a: 2 }; 15 | type Case2Baz = { c: 3 }; 16 | type MergeLeftAllCase2 = { 17 | a: 1; 18 | b: 2; 19 | c: 3; 20 | }; 21 | 22 | type Case3Foo = { a: 1; b: 2 }; 23 | type Case3Bar = { a: 2 }; 24 | type Case3Baz = { c: 3 }; 25 | type MergeRightAllCase3 = { 26 | a: 2; 27 | b: 2; 28 | c: 3; 29 | }; 30 | 31 | type cases = [ 32 | Expect, MergeAllCase1>>, 33 | Expect< 34 | Equal, MergeLeftAllCase2> 35 | >, 36 | Expect< 37 | Equal, MergeRightAllCase3> 38 | > 39 | ]; 40 | -------------------------------------------------------------------------------- /packages/core/PickByTypeExact/index.d.ts: -------------------------------------------------------------------------------- 1 | import { OmitNever } from "@utype/core"; 2 | import { Equal } from "@utype/shared"; 3 | 4 | /** 5 | * PickByTypeExact 6 | * @description From T pick a set of properties by value matching exact ValueType. 7 | * @alias PickByValueExact 8 | * @example 9 | * ```ts 10 | * type Prop = { 11 | * foo: number; 12 | * bar: number | undefined; 13 | * faz: string; 14 | * } 15 | * // Expect: { foo: number; } 16 | * type PickByTypeExactProp1 = PickByTypeExact 17 | * // Expect: { bar: number | undefined; } 18 | * type PickByTypeExactProp2 = PickByTypeExact 19 | * ``` 20 | */ 21 | export type PickByTypeExact = Pick< 22 | T, 23 | OmitNever<{ 24 | [K in keyof T]: Equal extends true ? K : never; 25 | }> 26 | >; 27 | 28 | // alias 29 | 30 | /** 31 | * PickByValueExact 32 | * @description Alias for PickByTypeExact 33 | */ 34 | export type PickByValueExact = PickByTypeExact; 35 | -------------------------------------------------------------------------------- /packages/shared/TupleHead/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import { TupleHead, Equal, Expect } from "@utype/shared"; 2 | 3 | type Case1 = []; 4 | type TupleHeadCase1 = never; 5 | 6 | type Case2 = [a: string, b: number, c: boolean]; 7 | type TupleHeadCase2 = [a: string]; 8 | 9 | type Case3 = readonly [a: string, b: number, c: boolean]; 10 | type TupleHeadCase3 = readonly [a: string]; 11 | 12 | type Case4 = [a: string, b?: number, c?: boolean]; 13 | type TupleHeadCase4 = [a: string]; 14 | 15 | type Case5 = [a?: string, b?: number, c?: boolean]; 16 | type TupleHeadCase5 = [a?: string]; 17 | 18 | type Case6 = readonly [a?: string, b?: number, c?: boolean]; 19 | type TupleHeadCase6 = readonly [a?: string]; 20 | 21 | type cases = [ 22 | Expect, TupleHeadCase1>>, 23 | Expect, TupleHeadCase2>>, 24 | Expect, TupleHeadCase3>>, 25 | Expect, TupleHeadCase4>>, 26 | Expect, TupleHeadCase5>>, 27 | Expect, TupleHeadCase6>> 28 | ]; 29 | -------------------------------------------------------------------------------- /packages/core/OmitByTypeExact/index.d.ts: -------------------------------------------------------------------------------- 1 | import { OmitNever } from "@utype/core"; 2 | import { Equal } from "@utype/shared"; 3 | 4 | /** 5 | * OmitByTypeExact 6 | * @description From T remove a set of properties by value matching exact ValueType. 7 | * @alias OmitByValueExact 8 | * @example 9 | * ```ts 10 | * type Prop = { 11 | * foo: number; 12 | * bar: number | undefined; 13 | * faz: boolean; 14 | * } 15 | * // Expect: { bar: number | undefined; faz: boolean; } 16 | * type OmitByTypeExactProp1 = OmitByTypeExact 17 | * // Expect: { foo: number; faz: boolean; } 18 | * type OmitByTypeExactProp2 = OmitByTypeExact 19 | * ``` 20 | */ 21 | export type OmitByTypeExact = Omit< 22 | T, 23 | OmitNever<{ 24 | [K in keyof T]: Equal extends true ? K : never; 25 | }> 26 | >; 27 | 28 | // alias 29 | 30 | /** 31 | * OmitByValueExact 32 | * @description Alias for OmitByTypeExact 33 | */ 34 | export type OmitByValueExact = OmitByTypeExact; 35 | -------------------------------------------------------------------------------- /packages/core/ObjectKeys/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { ObjectKeys } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | name: string; 6 | hobby: { title: string; description: string }; 7 | getName: () => string; 8 | }; 9 | type ObjectKeysCase1 = "hobby"; 10 | 11 | type Case2 = { 12 | name: string; 13 | hobby: { title: string; description: string }; 14 | sports?: { title: string; description: string }; 15 | getName?: () => string; 16 | }; 17 | type ObjectKeysCase2 = "hobby" | "sports"; 18 | 19 | type Case3 = { 20 | name: string; 21 | hobby: { title: string; description: string }; 22 | functionCase: () => string; 23 | mapCase: Map; 24 | weakmapCase: WeakMap<{}, number>; 25 | setCase: Set; 26 | weaksetCase: WeakSet<{}>; 27 | nullCase: null; 28 | }; 29 | type ObjectKeysCase3 = "hobby"; 30 | 31 | type cases = [ 32 | Expect, ObjectKeysCase1>>, 33 | Expect, ObjectKeysCase2>>, 34 | Expect, ObjectKeysCase3>> 35 | ]; 36 | -------------------------------------------------------------------------------- /packages/vue/ToEmitsForEvents/index.d.ts: -------------------------------------------------------------------------------- 1 | import { UnionToIntersection } from '@utype/core' 2 | 3 | /** 4 | * ToEmitsForEvents 5 | * @alias EventsToEmits 6 | * @description Converting Events to Emits 7 | * @example 8 | * ```ts 9 | * type Prop = { 10 | * onClick: (e: Event) => void; 11 | * onMousedown: () => void; 12 | * } 13 | * // Expect: { (eventname: "click", e: Event): void; (eventname: "mousedown"): void; } 14 | * type MyProp = ToEmitsForEvents 15 | * ``` 16 | */ 17 | export type ToEmitsForEvents = _ToEmitsForEvents> 18 | 19 | /** @private */ 20 | type _ToEmitsForEvents = UnionToIntersection< 21 | { 22 | [K in keyof T]: K extends `on${infer U}` 23 | ? T[K] extends (...args: infer E) => infer R 24 | ? (eventname: Lowercase, ...args: E) => R 25 | : never 26 | : never 27 | }[keyof T] 28 | > 29 | 30 | // alias 31 | 32 | /** 33 | * EventsToEmits 34 | * @description Alias for ToEmitsForEvents 35 | */ 36 | export type EventsToEmits = ToEmitsForEvents; 37 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "esnext", 4 | "target": "es2017", 5 | "declaration": true, 6 | "lib": ["ESNext"], 7 | "strict": true, 8 | "moduleResolution": "node", 9 | "paths": { 10 | "@utype/core": ["./packages/core/index.d.ts"], 11 | "@utype/core/*": ["./packages/core/*"], 12 | "@utype/vue": ["./packages/vue/index.d.ts"], 13 | "@utype/vue/*": ["./packages/vue/*"], 14 | "@utype/react": ["./packages/react/index.d.ts"], 15 | "@utype/react/*": ["./packages/react/*"], 16 | "@utype/shared": ["./packages/shared/index.d.ts"], 17 | "@utype/shared/*": ["./packages/shared/*"] 18 | }, 19 | "noUnusedLocals": false, 20 | "noUnusedParameters": true, 21 | "noImplicitAny": true, 22 | "noImplicitThis": true, 23 | "noImplicitReturns": true, 24 | "strictNullChecks": true, 25 | "strictFunctionTypes": true, 26 | "types": [], 27 | "noEmit": true, 28 | "forceConsistentCasingInFileNames": true 29 | }, 30 | "include": ["*.ts", "packages"], 31 | "exclude": ["node_modules", "dist"] 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 wzc520pyfm 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/core/DeepPartial/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { DeepPartial } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | a: () => 22; 6 | b: string; 7 | c: { 8 | d: boolean; 9 | e: { 10 | g: { 11 | h: { 12 | i: true; 13 | j: "string"; 14 | }; 15 | k: "hello"; 16 | }; 17 | l: [ 18 | "hi", 19 | { 20 | m: ["hey"]; 21 | } 22 | ]; 23 | }; 24 | }; 25 | }; 26 | type DeepPartialCase1 = { 27 | a?: () => 22; 28 | b?: string; 29 | c?: { 30 | d?: boolean; 31 | e?: { 32 | g?: { 33 | h?: { 34 | i?: true; 35 | j?: "string"; 36 | }; 37 | k?: "hello"; 38 | }; 39 | l?: [ 40 | "hi", 41 | { 42 | m: ["hey"]; 43 | } 44 | ]; 45 | }; 46 | }; 47 | }; 48 | 49 | type Case2 = { a: string } | { b: number }; 50 | type DeepPartialCase2 = { a?: string } | { b?: number }; 51 | 52 | type cases = [ 53 | Expect, DeepPartialCase1>>, 54 | Expect, DeepPartialCase2>> 55 | ]; 56 | -------------------------------------------------------------------------------- /packages/core/Curried/index.d.ts: -------------------------------------------------------------------------------- 1 | import { TupleHead } from "@utype/shared"; 2 | 3 | /** 4 | * Curried 5 | * @description [Currying](https://en.wikipedia.org/wiki/Currying) function with support for dynamic parameters. 6 | * 7 | * @use 8 | * ```ts 9 | * function yourCurrying( 10 | * fn: (...args: A) => R 11 | * ): Curried { 12 | * // Your implementation logic... 13 | * } 14 | * ``` 15 | * 16 | * @example 17 | * ```ts 18 | * const yourFun = (a: string, b: number) => true; 19 | * const curriedYourFun = yourCurrying(yourFun); 20 | * // Expect: 21 | * // ((a: string, b: number) => boolean) & 22 | * // ((a: string) => (b: number) => boolean) 23 | * type CurriedYourFun = typeof curriedYourFun; 24 | * // use: 25 | * const res1 = curriedYourFun('123', 123); 26 | * const res2 = curriedYourFun('123')(123); 27 | * ``` 28 | */ 29 | export type Curried = A extends [ 30 | unknown, 31 | ...infer T 32 | ] 33 | ? T extends [] 34 | ? (...args: [...D, ...TupleHead]) => R 35 | : ((...args: [...D, ...TupleHead]) => Curried) & 36 | Curried]> 37 | : () => R; 38 | -------------------------------------------------------------------------------- /packages/core/UnionToIntersection/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * UnionToIntersection 3 | * @description Get intersection type given union type U. 4 | * @alias Union2Intersection UToI U2I 5 | * @example 6 | * ```ts 7 | * type Prop = { name: string } | { age: number } | { visible: boolean } 8 | * // Expect: { name: string } & { age: number } & { visible: boolean } 9 | * type UnionToIntersectionProp = UnionToIntersection 10 | * // Expect: 'foo' & 42 & true 11 | * type Case = UnionToIntersection<'foo' | 42 | true> 12 | * ``` 13 | */ 14 | export type UnionToIntersection = _UnionToUFunctions extends (arg: infer I) => void ? I : never; 15 | 16 | /** @private */ 17 | export type _UnionToUFunctions = U extends any ? (arg: U) => any : never; 18 | 19 | // alias 20 | 21 | /** 22 | * Union2Intersection 23 | * @description Alias for UnionToIntersection 24 | */ 25 | export type Union2Intersection = UnionToIntersection; 26 | 27 | /** 28 | * UToI 29 | * @description Alias for UnionToIntersection 30 | */ 31 | export type UToI = UnionToIntersection; 32 | 33 | /** 34 | * U2I 35 | * @description Alias for UnionToIntersection 36 | */ 37 | export type U2I = UnionToIntersection; 38 | -------------------------------------------------------------------------------- /packages/core/DeepRequired/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { DeepRequired } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | a: () => 22; 6 | b?: string; 7 | c?: { 8 | d: boolean; 9 | e?: { 10 | g: { 11 | h?: { 12 | i: true; 13 | j?: "string"; 14 | }; 15 | k?: "hello"; 16 | }; 17 | l?: [ 18 | "hi", 19 | { 20 | m: ["hey"]; 21 | } 22 | ]; 23 | }; 24 | }; 25 | }; 26 | type DeepRequiredCase1 = { 27 | a: () => 22; 28 | b: string; 29 | c: { 30 | d: boolean; 31 | e: { 32 | g: { 33 | h: { 34 | i: true; 35 | j: "string"; 36 | }; 37 | k: "hello"; 38 | }; 39 | l: [ 40 | "hi", 41 | { 42 | m: ["hey"]; 43 | } 44 | ]; 45 | }; 46 | }; 47 | }; 48 | 49 | type TT = DeepRequired 50 | 51 | type Case2 = { a?: string } | { b?: number }; 52 | type DeepRequiredCase2 = { a: string } | { b: number }; 53 | 54 | type cases = [ 55 | Expect, DeepRequiredCase1>>, 56 | Expect, DeepRequiredCase2>> 57 | ]; 58 | -------------------------------------------------------------------------------- /packages/core/NonObjectKeys/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { NonObjectKeys } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | name: string; 6 | hobby: { title: string; description: string }; 7 | }; 8 | type NonObjectKeysCase1 = "name"; 9 | 10 | type Case2 = { 11 | name: string; 12 | hobby: { title: string; description: string }; 13 | sports?: { title: string; description: string }; 14 | getName?: () => string; 15 | }; 16 | type NonObjectKeysCase2 = "name" | "getName"; 17 | 18 | type Case3 = { 19 | name: string; 20 | hobby: { title: string; description: string }; 21 | functionCase: () => string; 22 | mapCase: Map; 23 | weakmapCase: WeakMap<{}, number>; 24 | setCase: Set; 25 | weaksetCase: WeakSet<{}>; 26 | nullCase: null; 27 | }; 28 | type NonObjectKeysCase3 = 29 | | "name" 30 | | "functionCase" 31 | | "mapCase" 32 | | "weakmapCase" 33 | | "setCase" 34 | | "weaksetCase" 35 | | "nullCase"; 36 | 37 | type cases = [ 38 | Expect, NonObjectKeysCase1>>, 39 | Expect, NonObjectKeysCase2>>, 40 | Expect, NonObjectKeysCase3>> 41 | ]; 42 | -------------------------------------------------------------------------------- /packages/core/DeepReadonly/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { DeepReadonly } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | a: () => 22; 6 | b: string; 7 | c: { 8 | d: boolean; 9 | e: { 10 | g: { 11 | h: { 12 | i: true; 13 | j: "string"; 14 | }; 15 | k: "hello"; 16 | }; 17 | l: [ 18 | "hi", 19 | { 20 | m: ["hey"]; 21 | } 22 | ]; 23 | }; 24 | }; 25 | }; 26 | type DeepReadonlyCase1 = { 27 | readonly a: () => 22; 28 | readonly b: string; 29 | readonly c: { 30 | readonly d: boolean; 31 | readonly e: { 32 | readonly g: { 33 | readonly h: { 34 | readonly i: true; 35 | readonly j: "string"; 36 | }; 37 | readonly k: "hello"; 38 | }; 39 | readonly l: readonly [ 40 | "hi", 41 | { 42 | readonly m: readonly ["hey"]; 43 | } 44 | ]; 45 | }; 46 | }; 47 | }; 48 | 49 | type Case2 = { a: string } | { b: number }; 50 | type DeepReadonlyCase2 = { readonly a: string } | { readonly b: number }; 51 | 52 | type cases = [ 53 | Expect, DeepReadonlyCase1>>, 54 | Expect, DeepReadonlyCase2>> 55 | ]; 56 | -------------------------------------------------------------------------------- /packages/core/DeepReadonlyX/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Keys, OnlyObject } from "@utype/shared"; 2 | import { MergeRight, DeepKeys } from "@utype/core"; 3 | 4 | /** 5 | * DeepReadonlyX 6 | * @description Make specified properties in the object readonly, regardless of how deeply nested they are. 7 | * @alias DeepReadonlyByKeys 8 | * @example 9 | * ```ts 10 | * type Prop = { 11 | * x: { 12 | * a: 1 13 | * b: 'hi' 14 | * }, 15 | * y: 'hey' 16 | * } 17 | * // Expect: { 18 | * // x: { 19 | * // a: 1, 20 | * // readonly b: 'hi' 21 | * // } 22 | * // readonly y: 'hey' 23 | * // } 24 | * type DeepReadonlyXProp = DeepReadonlyX 25 | * ``` 26 | */ 27 | // todo: The P should be constrained within DeepKeys 28 | export type DeepReadonlyX> = MergeRight< 29 | { 30 | [K in Exclude, P>]: K extends P 31 | ? never 32 | : T[K] extends OnlyObject 33 | ? DeepReadonlyX 34 | : T[K]; 35 | }, 36 | { 37 | readonly [K in Extract, P>]: T[K] extends OnlyObject 38 | ? DeepReadonlyX 39 | : K extends P 40 | ? T[K] 41 | : never; 42 | } 43 | >; 44 | 45 | // alias 46 | 47 | /** 48 | * DeepReadonlyByKeys 49 | * @description Alias for DeepReadonlyX 50 | */ 51 | export type DeepReadonlyByKeys> = DeepReadonlyX; 52 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to UType 2 | 3 | Thank you for your interest in contributing to UType! Whether you're reporting a bug, proposing a new feature, or contributing code or documentation, we appreciate your help. 4 | 5 | ## Issues 6 | 7 | If you find a bug or have a feature request, please [open an issue](https://github.com/wzc520pyfm/utype/issues). 8 | 9 | ## Pull Requests 10 | 11 | We welcome your pull requests. Before submitting a pull request, please make sure: 12 | 13 | - Your code follows the coding style of the project. 14 | - You have written tests for your changes (if applicable). 15 | - Your commits have clear commit messages. 16 | 17 | To submit a pull request: 18 | 19 | 1. Fork the repository. 20 | 2. Create a new branch for your feature or bug fix. 21 | 3. Make your changes and commit them. 22 | 4. Push to your fork and [submit a pull request](https://github.com/wzc520pyfm/utype/pulls). 23 | 24 | ## Code of Conduct 25 | 26 | This project follows a [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report any unacceptable behavior. 27 | 28 | ## License 29 | 30 | By contributing, you agree that your contributions will be licensed under the [MIT License](LICENSE). 31 | 32 | ## Contact 33 | 34 | If you have questions or need further assistance, feel free to contact us at wzc520pyf@163.com. 35 | 36 | Happy coding! 37 | -------------------------------------------------------------------------------- /packages/core/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './Mutable' 2 | export * from './DeepMutable' 3 | export * from './DeepReadonly' 4 | export * from './DeepPartial' 5 | export * from './DeepRequired' 6 | 7 | export * from './MutableX' 8 | export * from './ReadonlyX' 9 | export * from './PartialX' 10 | export * from './RequiredX' 11 | export * from './DeepReadonlyX' 12 | 13 | export * from './Merge' 14 | export * from './MergeAll' 15 | 16 | export * from './TwoTuple' 17 | export * from './Nullable' 18 | export * from './NonUndefined' 19 | export * from './OmitNever' 20 | export * from './UnionToIntersection' 21 | export * from './OptionalTupleLast' 22 | 23 | export * from "./DeepKeys"; 24 | export * from './ReadonlyKeys' 25 | export * from './MutableKeys' 26 | export * from './RequiredKeys' 27 | export * from './PartialKeys' 28 | export * from './FunctionKeys' 29 | export * from './NonFunctionKeys' 30 | export * from './ObjectKeys' 31 | export * from './NonObjectKeys' 32 | 33 | export * from './PickByType' 34 | export * from './PickByTypeFuzzy' 35 | export * from './PickByTypeExact' 36 | export * from './OmitByType' 37 | export * from './OmitByTypeFuzzy' 38 | export * from './OmitByTypeExact' 39 | export * from './Diff' 40 | export * from './Intersection' 41 | export * from './PickByRequired' 42 | 43 | export * from './KebabCase' 44 | export * from './SnakeCase' 45 | export * from './CamelCase' 46 | export * from './PascalCase' 47 | 48 | export * from './Curried' 49 | -------------------------------------------------------------------------------- /docs/public/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/core/MergeAll/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Merge, MergeLeft, MergeRight } from "@utype/core"; 2 | 3 | /** 4 | * MergeAll 5 | * @description Merge variadic number of types into a new type. If the keys overlap, its values should be merged into an union. 6 | * @example 7 | * ```ts 8 | * type Foo = { a: 1; b: 2 } 9 | * type Bar = { a: 2 } 10 | * type Baz = { c: 3 } 11 | * // Expect: { a: 1 | 2; b: 2; c: 3 } 12 | * type MergeAllResult = MergeAll<[Foo, Bar, Baz]> 13 | * ``` 14 | */ 15 | export type MergeAll = XS extends [infer First, ...infer Rest] 16 | ? MergeAll> 17 | : Prev; 18 | 19 | /** 20 | * MergeLeftAll 21 | * @description Merge variadic number of types into a new type. If the keys overlap, earlier keys override later keys. 22 | * @example 23 | * type Foo = { a: 1; b: 2 } 24 | * type Bar = { a: 2 } 25 | * type Baz = { c: 3 } 26 | * // Expect: { a: 1; b: 2; c: 3 } 27 | * type MergeAllResult = MergeAll<[Foo, Bar, Baz]> 28 | */ 29 | export type MergeLeftAll = XS extends [ 30 | infer First, 31 | ...infer Rest 32 | ] 33 | ? MergeLeftAll> 34 | : Prev; 35 | 36 | /** 37 | * MergeRightAll 38 | * @description Merge variadic number of types into a new type. If the keys overlap, later keys override earlier keys. 39 | * @example 40 | * type Foo = { a: 1; b: 2 } 41 | * type Bar = { a: 2 } 42 | * type Baz = { c: 3 } 43 | * // Expect: { a: 2; b: 2; c: 3 } 44 | * type MergeAllResult = MergeAll<[Foo, Bar, Baz]> 45 | */ 46 | export type MergeRightAll = XS extends [ 47 | infer First, 48 | ...infer Rest 49 | ] 50 | ? MergeRightAll> 51 | : Prev; 52 | -------------------------------------------------------------------------------- /packages/core/DeepMutable/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { DeepMutable } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | readonly title: string; 6 | readonly description: string; 7 | readonly completed: boolean; 8 | readonly meta: { 9 | readonly author: string; 10 | }; 11 | }; 12 | type DeepMutableCase1 = { 13 | title: string; 14 | description: string; 15 | completed: boolean; 16 | meta: { 17 | author: string; 18 | }; 19 | }; 20 | 21 | type Case2 = { 22 | readonly a: () => 1; 23 | readonly b: string; 24 | readonly c: { 25 | readonly d: boolean; 26 | readonly e: { 27 | readonly g: { 28 | readonly h: { 29 | readonly i: true; 30 | readonly j: "s"; 31 | }; 32 | readonly k: "hello"; 33 | }; 34 | readonly l: readonly [ 35 | "hi", 36 | { 37 | readonly m: readonly ["hey"]; 38 | } 39 | ]; 40 | }; 41 | }; 42 | }; 43 | type DeepMutableCase2 = { 44 | a: () => 1; 45 | b: string; 46 | c: { 47 | d: boolean; 48 | e: { 49 | g: { 50 | h: { 51 | i: true; 52 | j: "s"; 53 | }; 54 | k: "hello"; 55 | }; 56 | l: [ 57 | "hi", 58 | { 59 | m: ["hey"]; 60 | } 61 | ]; 62 | }; 63 | }; 64 | }; 65 | 66 | type Case3 = { readonly a: string } | { readonly b: number }; 67 | type DeepMutableCase3 = { a: string } | { b: number }; 68 | 69 | type cases = [ 70 | Expect, DeepMutableCase1>>, 71 | Expect, DeepMutableCase2>>, 72 | Expect, DeepMutableCase3>> 73 | ]; 74 | 75 | type errors = [ 76 | // @ts-expect-error 77 | DeepMutable<"string">, 78 | // @ts-expect-error 79 | DeepMutable<0> 80 | ]; 81 | -------------------------------------------------------------------------------- /packages/core/Merge/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { Merge, MergeLeft, MergeRight } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1Foo = { 5 | name: string; 6 | age: number; 7 | }; 8 | type Case1Bar = { 9 | age: number; 10 | sex: string; 11 | }; 12 | type MergeCase1 = { 13 | name: string; 14 | age: number; 15 | sex: string; 16 | }; 17 | 18 | type Case2Foo = { 19 | name: string; 20 | age: boolean; 21 | }; 22 | type Case2Bar = { 23 | age: number; 24 | sex: string; 25 | }; 26 | type MergeCase2 = { 27 | name: string; 28 | age: number | boolean; 29 | sex: string; 30 | }; 31 | 32 | type Case3Foo = { 33 | readonly name: string; 34 | readonly tt?: string; 35 | age?: boolean; 36 | }; 37 | type Case3Bar = { 38 | tt: string[]; 39 | age: number; 40 | sex?: string; 41 | }; 42 | type MergeCase3 = { 43 | readonly name: string; 44 | readonly tt?: string | string[]; 45 | age?: number | boolean; 46 | sex?: string; 47 | }; 48 | 49 | type Case4Foo = { 50 | readonly name: string; 51 | readonly tt?: string; 52 | age: boolean; 53 | }; 54 | type Case4Bar = { 55 | tt: string[]; 56 | age?: number; 57 | sex?: string; 58 | }; 59 | type MergeLeftCase4 = { 60 | readonly name: string; 61 | readonly tt?: string; 62 | age: boolean; 63 | sex?: string; 64 | }; 65 | 66 | type Case5Foo = { 67 | readonly name: string; 68 | readonly tt?: string; 69 | age: boolean; 70 | }; 71 | type Case5Bar = { 72 | tt: string[]; 73 | age?: number; 74 | sex?: string; 75 | }; 76 | type MergeRightCase5 = { 77 | readonly name: string; 78 | tt: string[]; 79 | age?: number; 80 | sex?: string; 81 | }; 82 | 83 | type cases = [ 84 | Expect, MergeCase1>>, 85 | Expect, MergeCase2>>, 86 | Expect, MergeCase3>>, 87 | Expect, MergeLeftCase4>>, 88 | Expect, MergeRightCase5>> 89 | ]; 90 | -------------------------------------------------------------------------------- /packages/core/DeepReadonlyX/index.d.test.ts: -------------------------------------------------------------------------------- 1 | import type { DeepReadonlyX } from "@utype/core"; 2 | import { Equal, Expect } from "@utype/shared"; 3 | 4 | type Case1 = { 5 | a: 1; 6 | b: "hi"; 7 | }; 8 | type DeepReadonlyXCase1 = { 9 | a: 1; 10 | readonly b: "hi"; 11 | }; 12 | 13 | type Case2 = { 14 | x: { 15 | a: 1; 16 | b: "hi"; 17 | }; 18 | y: "hey"; 19 | }; 20 | type DeepReadonlyXCase2 = { 21 | x: { 22 | a: 1; 23 | readonly b: "hi"; 24 | }; 25 | readonly y: "hey"; 26 | }; 27 | 28 | type Case3 = { 29 | x: { 30 | a: 1; 31 | b: "hi"; 32 | }; 33 | y: "hey"; 34 | }; 35 | type DeepReadonlyXCase3 = { 36 | readonly x: { 37 | readonly a: 1; 38 | readonly b: "hi"; 39 | }; 40 | readonly y: "hey"; 41 | }; 42 | 43 | type Case4 = { 44 | a: () => 22; 45 | b: string; 46 | c: { 47 | d: boolean; 48 | e: { 49 | g: { 50 | h: { 51 | i: true; 52 | j: "string"; 53 | }; 54 | k: "hello"; 55 | }; 56 | l: [ 57 | "hi", 58 | { 59 | m: ["hey"]; 60 | } 61 | ]; 62 | }; 63 | }; 64 | }; 65 | type DeepReadonlyXCase4 = { 66 | a: () => 22; 67 | b: string; 68 | c: { 69 | d: boolean; 70 | readonly e: { 71 | g: { 72 | readonly h: { 73 | i: true; 74 | j: "string"; 75 | }; 76 | k: "hello"; 77 | }; 78 | l: [ 79 | "hi", 80 | { 81 | m: ["hey"]; 82 | } 83 | ]; 84 | }; 85 | }; 86 | }; 87 | 88 | type Case5 = { 89 | x: { 90 | a: 1; 91 | b: "hi"; 92 | }; 93 | b: "hey"; 94 | }; 95 | type DeepReadonlyXCase5 = { 96 | x: { 97 | a: 1; 98 | readonly b: "hi"; 99 | }; 100 | readonly b: "hey"; 101 | }; 102 | 103 | // todo need support 104 | type Case6 = { a: string } | { b: number }; 105 | type DeepReadonlyXCase6 = { readonly a: string } | { readonly b: number }; 106 | 107 | type cases = [ 108 | Expect, DeepReadonlyXCase1>>, 109 | Expect, DeepReadonlyXCase2>>, 110 | Expect, DeepReadonlyXCase3>>, 111 | Expect, DeepReadonlyXCase4>>, 112 | Expect, DeepReadonlyXCase5>> 113 | // todo need support 114 | // Expect, DeepReadonlyXCase6>>, 115 | ]; 116 | -------------------------------------------------------------------------------- /packages/core/Merge/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Duplicate, Keys } from "@utype/shared"; 2 | import { ReadonlyKeys, PartialKeys } from "@utype/core"; 3 | 4 | /** 5 | * Merge 6 | * @description Merge two types into a new type. If the keys overlap, its values should be merged into an union. 7 | * @example 8 | * ```ts 9 | * type Foo = { 10 | * name: string; 11 | * age: string; 12 | * } 13 | * type Bar = { 14 | * age: number; 15 | * sex: string; 16 | * } 17 | * // Expect: { 18 | * // name: string; 19 | * // age: number | string; 20 | * // sex: string; 21 | * // } 22 | * type MergeResult = Merge 23 | * ``` 24 | */ 25 | export type Merge = Duplicate< 26 | { 27 | [K in Exclude< 28 | Keys | Keys, 29 | ReadonlyKeys | ReadonlyKeys | PartialKeys | PartialKeys 30 | >]: F[K & Keys] | S[K & Keys]; 31 | } & { 32 | readonly [K in Exclude< 33 | ReadonlyKeys | ReadonlyKeys, 34 | PartialKeys | PartialKeys 35 | >]: F[K & Keys] | S[K & Keys]; 36 | } & { 37 | readonly [K in Extract< 38 | ReadonlyKeys | ReadonlyKeys, 39 | PartialKeys | PartialKeys 40 | >]?: F[K & Keys] | S[K & Keys]; 41 | } & { 42 | [K in Exclude< 43 | PartialKeys | PartialKeys, 44 | ReadonlyKeys | ReadonlyKeys 45 | >]?: F[K & Keys] | S[K & Keys]; 46 | } 47 | >; 48 | 49 | /** 50 | * MergeLeft 51 | * @description Merge two types into a new type. Keys of the first type overrides keys of the second type. 52 | * @example 53 | * type Foo = { 54 | * name: string; 55 | * age: string; 56 | * } 57 | * type Bar = { 58 | * age: number; 59 | * sex: string; 60 | * } 61 | * // Expect: { 62 | * // name: string; 63 | * // age: string; 64 | * // sex: string; 65 | * // } 66 | * type MergeLeftResult = MergeLeft 67 | */ 68 | export type MergeLeft = Duplicate> & F>; 69 | 70 | /** 71 | * MergeRight 72 | * @description Merge two types into a new type. Keys of the second type overrides keys of the first type. 73 | * @example 74 | * type Foo = { 75 | * name: string; 76 | * age: string; 77 | * } 78 | * type Bar = { 79 | * age: number; 80 | * sex: string; 81 | * } 82 | * // Expect: { 83 | * // name: string; 84 | * // age: number; 85 | * // sex: string; 86 | * // } 87 | * type MergeRightResult = MergeRight 88 | */ 89 | export type MergeRight = Duplicate> & S>; 90 | -------------------------------------------------------------------------------- /packages/core/Curried/index.test.ts: -------------------------------------------------------------------------------- 1 | import { Curried } from "@utype/core"; 2 | import { Expect, Equal } from "@utype/shared"; 3 | 4 | // test func 5 | declare function DynamicParamsCurrying( 6 | fn: (...args: A) => R 7 | ): Curried; 8 | 9 | const curried1 = DynamicParamsCurrying( 10 | (_a: string, _b: number, _c: boolean) => true 11 | ); 12 | const curried2 = DynamicParamsCurrying( 13 | ( 14 | _a: string, 15 | _b: number, 16 | _c: boolean, 17 | _d: boolean, 18 | _e: boolean, 19 | _f: string, 20 | _g: boolean 21 | ) => true 22 | ); 23 | 24 | type Curried1Type = (( 25 | _a: string 26 | ) => ((_b: number) => (_c: boolean) => boolean) & 27 | ((_b: number, _c: boolean) => boolean)) & 28 | ((_a: string, _b: number) => (_c: boolean) => boolean) & 29 | ((_a: string, _b: number, _c: boolean) => boolean); 30 | 31 | const curried1Return1 = curried1("123")(123)(true); 32 | const curried1Return2 = curried1("123", 123)(false); 33 | const curried1Return3 = curried1("123")(123, false); 34 | const curried1Return4 = curried1("123", 123, true); 35 | 36 | const curried2Return1 = curried2("123")(123)(true)(false)(true)("123")(false); 37 | const curried2Return2 = curried2("123", 123)(true, false)(true, "123")(false); 38 | const curried2Return3 = curried2("123", 123)(true)(false)(true, "123", false); 39 | const curried2Return4 = curried2("123", 123, true)(false, true, "123")(false); 40 | const curried2Return5 = curried2("123", 123, true)(false)(true)("123")(false); 41 | const curried2Return6 = curried2("123", 123, true, false)(true, "123", false); 42 | const curried2Return7 = curried2("123", 123, true, false, true)("123", false); 43 | const curried2Return8 = curried2("123", 123, true, false, true)("123")(false); 44 | const curried2Return9 = curried2("123", 123, true, false, true, "123")(false); 45 | const curried2Return10 = curried2("123", 123, true, false, true, "123", false); 46 | 47 | type cases = [ 48 | // check preserves parameter names 49 | Expect>, 50 | 51 | // check return type 52 | Expect>, 53 | Expect>, 54 | Expect>, 55 | Expect>, 56 | 57 | // check more params 58 | Expect>, 59 | Expect>, 60 | Expect>, 61 | Expect>, 62 | Expect>, 63 | Expect>, 64 | Expect>, 65 | Expect>, 66 | Expect>, 67 | Expect> 68 | ]; 69 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at hi@element-plus.org. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq -------------------------------------------------------------------------------- /docs/.vitepress/pages/types.json: -------------------------------------------------------------------------------- 1 | { 2 | "core": { 3 | "text": "Core", 4 | "items": [ 5 | { 6 | "link": "/mutable", 7 | "text": "Mutable" 8 | }, 9 | { 10 | "link": "/deep-mutable", 11 | "text": "DeepMutable" 12 | }, 13 | { 14 | "link": "/deep-readonly", 15 | "text": "DeepReadonly" 16 | }, 17 | { 18 | "link": "/deep-partial", 19 | "text": "DeepPartial" 20 | }, 21 | { 22 | "link": "/deep-required", 23 | "text": "DeepRequired" 24 | }, 25 | { 26 | "link": "/mutable-x", 27 | "text": "MutableX" 28 | }, 29 | { 30 | "link": "/readonly-x", 31 | "text": "ReadonlyX" 32 | }, 33 | { 34 | "link": "/partial-x", 35 | "text": "PartialX" 36 | }, 37 | { 38 | "link": "/required-x", 39 | "text": "RequiredX" 40 | }, 41 | { 42 | "link": "/deep-readonly-x", 43 | "text": "DeepReadonlyX" 44 | }, 45 | { 46 | "link": "/merge", 47 | "text": "Merge" 48 | }, 49 | { 50 | "link": "/merge-left", 51 | "text": "MergeLeft" 52 | }, 53 | { 54 | "link": "/merge-right", 55 | "text": "MergeRight" 56 | }, 57 | { 58 | "link": "/merge-all", 59 | "text": "MergeAll" 60 | }, 61 | { 62 | "link": "/merge-left-all", 63 | "text": "MergeLeftAll" 64 | }, 65 | { 66 | "link": "/merge-right-all", 67 | "text": "MergeRightAll" 68 | }, 69 | { 70 | "link": "/two-tuple", 71 | "text": "TwoTuple" 72 | }, 73 | { 74 | "link": "/nullable", 75 | "text": "Nullable" 76 | }, 77 | { 78 | "link": "/non-undefined", 79 | "text": "NonUndefined" 80 | }, 81 | { 82 | "link": "/omit-never", 83 | "text": "OmitNever" 84 | }, 85 | { 86 | "link": "/union-to-intersection", 87 | "text": "UnionToIntersection" 88 | }, 89 | { 90 | "link": "/optional-tuple-last", 91 | "text": "OptionalTupleLast" 92 | }, 93 | { 94 | "link": "/deep-keys", 95 | "text": "DeepKeys" 96 | }, 97 | { 98 | "link": "/readonly-keys", 99 | "text": "ReadonlyKeys" 100 | }, 101 | { 102 | "link": "/mutable-keys", 103 | "text": "MutableKeys" 104 | }, 105 | { 106 | "link": "/required-keys", 107 | "text": "RequiredKeys" 108 | }, 109 | { 110 | "link": "/partial-keys", 111 | "text": "PartialKeys" 112 | }, 113 | { 114 | "link": "/function-keys", 115 | "text": "FunctionKeys" 116 | }, 117 | { 118 | "link": "/non-function-keys", 119 | "text": "NonFunctionKeys" 120 | }, 121 | { 122 | "link": "/object-keys", 123 | "text": "ObjectKeys" 124 | }, 125 | { 126 | "link": "/non-object-keys", 127 | "text": "NonObjectKeys" 128 | }, 129 | { 130 | "link": "/pick-by-type", 131 | "text": "PickByType" 132 | }, 133 | { 134 | "link": "/pick-by-type-fuzzy", 135 | "text": "PickByTypeFuzzy" 136 | }, 137 | { 138 | "link": "/pick-by-type-exact", 139 | "text": "PickByTypeExact" 140 | }, 141 | { 142 | "link": "/omit-by-type", 143 | "text": "OmitByType" 144 | }, 145 | { 146 | "link": "/omit-by-type-fuzzy", 147 | "text": "OmitByTypeFuzzy" 148 | }, 149 | { 150 | "link": "/omit-by-type-exact", 151 | "text": "OmitByTypeExact" 152 | }, 153 | { 154 | "link": "/diff", 155 | "text": "Diff" 156 | }, 157 | { 158 | "link": "/intersection", 159 | "text": "Intersection" 160 | }, 161 | { 162 | "link": "/pick-by-required", 163 | "text": "PickByRequired" 164 | }, 165 | { 166 | "link": "/kebab-case", 167 | "text": "KebabCase" 168 | }, 169 | { 170 | "link": "/snake-case", 171 | "text": "SnakeCase" 172 | }, 173 | { 174 | "link": "/camel-case", 175 | "text": "CamelCase" 176 | }, 177 | { 178 | "link": "/pascal-case", 179 | "text": "PascalCase" 180 | }, 181 | { 182 | "link": "/curried", 183 | "text": "Curried" 184 | } 185 | ] 186 | }, 187 | "shared": { 188 | "text": "Shared", 189 | "items": [ 190 | { 191 | "link": "/equal", 192 | "text": "Equal" 193 | }, 194 | { 195 | "link": "/expect", 196 | "text": "Expect" 197 | }, 198 | { 199 | "link": "/tuple-head", 200 | "text": "TupleHead" 201 | }, 202 | { 203 | "link": "/record-union", 204 | "text": "RecordToUnion" 205 | } 206 | ] 207 | }, 208 | "react": { 209 | "text": "React", 210 | "items": [ 211 | { 212 | "link": "/example-react", 213 | "text": "ExampleReact" 214 | } 215 | ] 216 | }, 217 | "vue": { 218 | "text": "Vue", 219 | "items": [ 220 | { 221 | "link": "/to-maybe-ref-or-getters", 222 | "text": "ToMaybeRefOrGetters" 223 | }, 224 | { 225 | "link": "/to-maybe-ref-or-getters-for-non-function", 226 | "text": "ToMaybeRefOrGettersForNonFunction" 227 | }, 228 | { 229 | "link": "/to-emits-for-events", 230 | "text": "ToEmitsForEvents" 231 | } 232 | ] 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## 🦄 Usage 3 | 4 | ```ts 5 | import type { Mutable } from '@utype/core' 6 | 7 | type Props = { readonly name: string; } 8 | 9 | // Expect: { name: string } 10 | type MutableProp = Mutable 11 | ``` 12 | 13 | ## 📦 Install 14 | 15 | ```bash 16 | npm i @utype/core 17 | ``` 18 | 19 | ## ✨ Types 20 | 21 | ### 🚀 Object Operation 22 | 23 | Mutable 24 | DeepMutable 25 | DeepReadonly 26 | DeepPartial 27 | DeepRequired 28 | 29 | ### 🚀 X Series 30 | 31 | MutableX 32 | PartialX 33 | RequiredX 34 | ReadonlyX 35 | DeepReadonlyX 36 | 37 | ### 🚀 Merge Object 38 | 39 | Merge 40 | MergeAll 41 | 42 | ### 🚀 Basic Operation 43 | 44 | TwoTuple 45 | Nullable 46 | NonUndefined 47 | OmitNever 48 | UnionToIntersection 49 | OptionalTupleLast 50 | RecordToUnion 51 | 52 | ### 🚀 Get Object Keys 53 | 54 | ReadonlyKeys 55 | MutableKeys 56 | RequiredKeys 57 | PartialKeys 58 | FunctionKeys 59 | NonFunctionKeys 60 | ObjectKeys 61 | NonObjectKeys 62 | 63 | ### 🚀 Generate Object 64 | 65 | PickByType 66 | PickByTypeFuzzy 67 | PickByTypeExact 68 | OmitByType 69 | OmitByTypeFuzzy 70 | OmitByTypeExact 71 | Diff 72 | Intersection 73 | PickByRequired 74 | 75 | ### 🚀 String Operation 76 | 77 | KebabCase 78 | SnakeCase 79 | CamelCase 80 | PascalCase 81 | 82 | ### 🚀 Function 83 | 84 | Curried 85 | 86 | ### Vue Reactive 87 | 88 | ToMaybeRefOrGetters 89 | ToMaybeRefOrGettersForNonFunction 90 | ToEmitsForEvents 91 | 92 | ## 🥰 Contributors 93 | 94 | 95 | 96 | 97 | --------------------------------------------------------------------------------