├── .gitignore ├── documents ├── document │ ├── README.md │ ├── 7.其他.md │ ├── 4.function.md │ ├── 6.common.md │ ├── 5.object.md │ ├── 1.number.md │ ├── 3.array.md │ └── 2.string.md ├── guide │ ├── README.md │ ├── 快速上手.md │ └── 介绍.md ├── .vuepress │ ├── config.js │ ├── public │ │ └── logo.svg │ └── sidebar.js └── README.md ├── .vscode └── settings.json ├── index.ts ├── test ├── function.test.ts ├── number.test.ts ├── common.test.ts ├── object.test.ts ├── string.test.ts └── array.test.ts ├── .github └── workflows │ └── gh-pages.yml ├── package.json ├── README.md ├── LICENSE ├── lib ├── function.ts ├── object.ts ├── common.ts ├── string.ts ├── array.ts └── number.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /documents/document/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /documents/guide/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib" 3 | } -------------------------------------------------------------------------------- /documents/document/7.其他.md: -------------------------------------------------------------------------------- 1 | # 其他 2 | 3 | ## 默认工具类型 4 | 5 | [参考 TypeScript 自带工具类型](https://www.typescriptlang.org/docs/handbook/utility-types.html) -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | export * as array from './lib/array' 2 | 3 | export * as common from './lib/common' 4 | 5 | export * as number from './lib/number' 6 | 7 | export * as object from './lib/object' 8 | 9 | export * as string from './lib/string' 10 | 11 | export * as function from './lib/function' -------------------------------------------------------------------------------- /documents/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | const package = require('../../package.json') 2 | 3 | module.exports = { 4 | title: "TypeScript-Lodash", 5 | description: "TypeScript 的工具类型集合", 6 | base: `/${package.name}/`, 7 | dest: './docs', 8 | head: [ 9 | ['link', { rel: 'icon', href: `/logo.svg` }], 10 | ], 11 | evergreen: true, 12 | themeConfig: { 13 | lastUpdated: '最后更新时间', 14 | sidebar: require('./sidebar').sidebar, 15 | nav: require('./sidebar').nav, 16 | displayAllHeaders: true 17 | }, 18 | } 19 | 20 | -------------------------------------------------------------------------------- /test/function.test.ts: -------------------------------------------------------------------------------- 1 | import * as t from ".." 2 | 3 | const request = async (id: number) => { 4 | return { 5 | code: 0, 6 | success: true, 7 | data: [], 8 | } 9 | } 10 | 11 | type ResultGetAsyncFunctionReturnType = t.function.GetAsyncFunctionReturnType< 12 | typeof request 13 | > 14 | 15 | type ResultGetFunctionLength = t.function.GetFunctionLength 16 | 17 | const bindTest = function (this: null, _arg0: number, _arg1: any) {} 18 | 19 | type ResultBind = t.function.Bind 20 | 21 | export type { 22 | ResultGetAsyncFunctionReturnType, 23 | ResultGetFunctionLength, 24 | ResultBind, 25 | } 26 | -------------------------------------------------------------------------------- /documents/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | heroImage: /logo.svg 4 | actionText: 快速上手 → 5 | actionLink: /guide/介绍.html 6 | features: 7 | - title: 类型体操 8 | details: 像做体操运动一样花里胡哨(褒义),为中国冬奥会加油 9 | - title: 使用友好 10 | details: 仿 JavaScript 常见实例原型方法,用 TS 工具类型就像在写 JS 11 | - title: 持续更新 12 | details: 你能想到的,你不能想到的我都要更新 13 | footer: MIT Licensed | Copyright © 2022-present kawayiLinLin 14 | --- 15 | 16 | ### 写 TS 像写 JS 一样容易 17 | 18 | 安装 19 | 20 | ```bash 21 | yarn add typescript-lodash # 或者:npm install -S typescript-lodash 22 | ``` 23 | 24 | 使用 25 | 26 | ```ts 27 | import { string } from "typescript-lodash" 28 | 29 | type IString = "今天很高兴" 30 | 31 | type TypeExample = string.Split 32 | 33 | // 得到 34 | type TypeResult = ["今", "天", "很", "高", "兴"] 35 | ``` 36 | 37 | ::: warning 注意 38 | 请确保你项目的 TypeScript 版本 >= 4.5.0。 39 | ::: -------------------------------------------------------------------------------- /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: GitHub Actions Build and Deploy Gh-pages 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | build-and-deploy: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 🛎️ 11 | uses: actions/checkout@master 12 | 13 | - name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. 14 | run: | 15 | npm install 16 | npm run build 17 | 18 | - name: Deploy 🚀 19 | uses: JamesIves/github-pages-deploy-action@v4.2.3 20 | with: 21 | branch: gh-pages # The branch the action should deploy to. 22 | folder: docs # The folder the action should deploy. -------------------------------------------------------------------------------- /documents/guide/快速上手.md: -------------------------------------------------------------------------------- 1 | # 快速上手 2 | 3 | ## 安装 4 | 5 | ```bash 6 | npm install -S typescript-lodash 7 | ``` 8 | 9 | ## 使用 10 | 11 | 按模块批量导入 12 | 13 | ```ts 14 | import { string } from "typescript-lodash" 15 | 16 | type IString = "今天很高兴" 17 | 18 | type TypeExample = string.Split 19 | 20 | // 得到 21 | type TypeResult = ["今", "天", "很", "高", "兴"] 22 | ``` 23 | 24 | 整体导入 25 | 26 | ```ts 27 | import * as t from 'typescript-lodash' 28 | 29 | type TypeExample = t.string.Split<"今天很高兴", ""> 30 | ``` 31 | 32 | 分模块导入 33 | 34 | ```ts 35 | import { Split } from 'typescript-lodash/lib' 36 | 37 | type TypeExample = Split<"今天很高兴", ""> 38 | ``` 39 | 40 | 41 | 详细使用请参考:[文档](/document/1.number.html) 42 | 43 | ::: warning 注意 44 | 使用 Typescript-Lodash 版本 <=0.1.0 时请确保你项目的 TypeScript 版本 >= 4.5.0。 45 | 46 | 使用 Typescript-Lodash 版本 >=0.2.0 时请确保你项目的 TypeScript 版本 >= 4.8.0。 47 | ::: -------------------------------------------------------------------------------- /test/number.test.ts: -------------------------------------------------------------------------------- 1 | import * as number from "../lib/number" 2 | import * as string from "../lib/string" 3 | 4 | type ResultIsZero = number.IsZero<-0> 5 | 6 | type ResultIsLessZero = number.IsLessZero<-1> 7 | 8 | type ResultIsOverZero = number.IsOverZero<"+1"> 9 | 10 | type ResultIsInt = number.IsInt<0> 11 | 12 | type ResultIsFloat = number.IsFloat<1.0, false> 13 | 14 | type ResultIsEqual = number.IsEqual<1, 1> 15 | 16 | type ResultIntIncrease = number.IntIncrease<9999999> 17 | 18 | type ResultIntAddSimple = number.IntAddSimple<999, 999> 19 | 20 | type ResultCompare = number.Compare<999, 998> 21 | 22 | type ResultGetHalf = number.GetHalf<0> 23 | 24 | type ResultToNumber = number.ToNumber<"9999"> 25 | 26 | type ResultAdd = number.Add<"9007199254740991.12345", "9007199254740991.234567"> 27 | 28 | type ResultParseFloat = number.ParseFloat<"-3.14159265358979300000000000"> 29 | 30 | export type { 31 | ResultIsZero, 32 | ResultIsLessZero, 33 | ResultIsOverZero, 34 | ResultIsInt, 35 | ResultIsFloat, 36 | ResultIsEqual, 37 | ResultIntIncrease, 38 | ResultIntAddSimple, 39 | ResultCompare, 40 | ResultGetHalf, 41 | ResultToNumber, 42 | ResultAdd, 43 | ResultParseFloat 44 | } 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-lodash", 3 | "version": "0.2.1", 4 | "description": "A TypeScript Utility Types lib", 5 | "main": "./index", 6 | "module": "./index", 7 | "scripts": { 8 | "dev": "vuepress dev documents", 9 | "build": "vuepress build documents", 10 | "pub": "npm publish --registry=https://registry.npmjs.org", 11 | "login": "npm login --registry=https://registry.npmjs.org", 12 | "postpublish": "git push origin master & git push github master & git push github --tag & git push origin --tag" 13 | }, 14 | "files": [ 15 | "lib", 16 | "test", 17 | "index.ts", 18 | "tsconfig.json", 19 | "LICENSE" 20 | ], 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/kawayiLinLin/typescript-lodash.git" 24 | }, 25 | "homepage": "https://kawayiLinLin.github.io/typescript-lodash", 26 | "keywords": [ 27 | "typescript", 28 | "Utility", 29 | "Types", 30 | "tool", 31 | "util", 32 | "ts", 33 | "TS", 34 | "TypeScript" 35 | ], 36 | "author": "kawayilinlin", 37 | "license": "MIT", 38 | "devDependencies": { 39 | "typescript": "^4.8.2", 40 | "vuepress": "^1.9.7" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/common.test.ts: -------------------------------------------------------------------------------- 1 | import { common } from ".." 2 | 3 | type ResultAnd = common.And 4 | 5 | type ResultOr = common.Or 6 | 7 | type ResultNot = common.Not 8 | 9 | type ResultCheckLeftIsExtendsRight = common.CheckLeftIsExtendsRight<1, 2> 10 | 11 | type ResultIsEqual = common.IsEqual<1, number> 12 | 13 | type ResultIsAny = common.IsAny 14 | 15 | type ResultIsNever = common.IsNever 16 | 17 | type ResultIsUnion = common.IsUnion<1 | 2> 18 | 19 | type ResultDiff = common.Diff<1 | 2, 1 | 3> 20 | 21 | type ResultSumAggregate = common.SumAggregate<1 | 2, 1 | 3> 22 | 23 | type ResultNullable = common.Nullable<1> 24 | 25 | type ResultMany = common.Many 26 | 27 | type ResultUnionToIntersection = common.UnionToIntersection<{ a: 1 } | { b: 2 }> 28 | 29 | type ResultUnionToTuple = common.UnionToTuple<1 | 2 | 3> 30 | 31 | export type { 32 | ResultAnd, 33 | ResultOr, 34 | ResultNot, 35 | ResultCheckLeftIsExtendsRight, 36 | ResultIsEqual, 37 | ResultIsAny, 38 | ResultIsNever, 39 | ResultIsUnion, 40 | ResultDiff, 41 | ResultSumAggregate, 42 | ResultNullable, 43 | ResultMany, 44 | ResultUnionToTuple, 45 | ResultUnionToIntersection, 46 | } 47 | -------------------------------------------------------------------------------- /documents/guide/介绍.md: -------------------------------------------------------------------------------- 1 | # 介绍 2 | 3 | TypeScript 是具有类型语法的 JavaScript,是一种基于 JavaScript 的强类型编程语言,一般来讲,我们可以通过 TypeScript 编写大型的应用程序,但是其 runtime 本质还是在执行 JavaScript 脚本 4 | 5 | 如果我们能用 TypeScript 本身的类型系统来编写复杂的逻辑呢? 6 | 7 | 或者拥有一套 TypeScript 工具类型([Utility Types](https://www.typescriptlang.org/docs/handbook/utility-types.html))让我们通过更好的处理类型来编写更好的 TypeScript 应用? 8 | 9 | ## 它是如何工作的 10 | 11 | TypeScript-Lodash 基于 TypeScript 4.5.0 以上版本,封装了操作[元](https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types)([数](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#arrays))组类型、[模板字符串类型](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html#template-literal-types)、[对象类型](https://www.typescriptlang.org/docs/handbook/2/objects.html)、[函数类型](https://www.typescriptlang.org/docs/handbook/2/functions.html)、[联合类型](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types)、[条件类型](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html) 等的工具类型 12 | 13 | ## 它能用来做什么 14 | 15 | 你可以基于它进行基本的类型逻辑运算操作 `common.And` 等;基本的类型数学运算操作 `number.IntAndSingle<1, 2>`、`number.Compare<2, 1>` 等;高级的元(数)组类型操作 `array.Join<[1, 2, 3]>`、`string.Split<"1,2,3", ",">`;或者基于它封装更有趣的有用的工具类型、有复杂逻辑的类型计算,就像你可以用它模拟一个中国象棋,参考 `common.Add<"1.01", "22.225">` 大数模板字符串类型加法的实现。 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 写 TS 像写 JS 一样容易 2 | 3 | [![OSCS Status](https://www.oscs1024.com/platform/badge/kawayiLinLin/typescript-lodash.svg?size=small)](https://www.oscs1024.com/project/kawayiLinLin/typescript-lodash?ref=badge_small) [![NPM URL](https://img.shields.io/badge/npm-v6.14.12-1577b4)](https://www.npmjs.com/package/typescript-lodash) [![Typescript Limit](https://img.shields.io/badge/TypeScript->=4.8.2-1577b4)](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) [![NPM URL](https://img.shields.io/badge/license-MIT-8fba29)](https://www.npmjs.com/package/typescript-lodash) 4 | 5 | Make writing TypeScript as easy as writing JavaScript 6 | 7 | 安装 Install 8 | 9 | ```bash 10 | yarn add typescript-lodash # or:npm install --save typescript-lodash 11 | ``` 12 | 13 | 使用 Usage 14 | 15 | ```ts 16 | import { string } from "typescript-lodash" 17 | // or use `import * as t from "typescript-lodash"` and then `t.string.Split<"">` 18 | // or use `import { Split } from "typescript-lodash/lib/string"` and then `Split<"">` 19 | 20 | type IString = "今天很高兴" 21 | 22 | type TypeExample = string.Split 23 | 24 | // 得到 25 | type TypeResult = ["今", "天", "很", "高", "兴"] 26 | ``` 27 | 28 | 查看文档 Documentation 29 | 30 | [中文文档 Chinese Documentation](https://kawayilinlin.github.io/typescript-lodash/) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Linden Research, Inc. 3 | Copyright (c) 2012, Joshua Bell 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 13 | all 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 21 | THE SOFTWARE. 22 | $/LicenseInfo$ 23 | */ 24 | 25 | // Original can be found at: 26 | // https://bitbucket.org/lindenlab/llsd 27 | // Modifications by Joshua Bell inexorabletash@gmail.com 28 | // https://github.com/inexorabletash/polyfill -------------------------------------------------------------------------------- /lib/function.ts: -------------------------------------------------------------------------------- 1 | import { array, number } from '..' 2 | 3 | type Noop = (...args: any) => any 4 | 5 | /** 6 | * Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`. 7 | */ 8 | type Awaited = 9 | T extends null | undefined ? T : // special case for `null | undefined` when not in `--strictNullChecks` mode 10 | T extends object & { then(onfulfilled: infer F): any } ? // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped 11 | F extends ((value: infer V, ...args: any) => any) ? // if the argument to `then` is callable, extracts the first argument 12 | Awaited : // recursively unwrap the value 13 | never : // the argument to `then` was not callable 14 | T; // non-object or non-thenable 15 | 16 | type GetAsyncFunctionReturnType = Awaited> 17 | 18 | type GetFunctionLength = F extends (...args: infer P) => any 19 | ? P["length"] 20 | : never 21 | 22 | type Bind< 23 | F extends Noop, 24 | NewThisType = null, 25 | NewParams extends unknown[] = [] 26 | > = F extends (this: infer T, ...args: infer P) => infer R 27 | ? (this: NewThisType, ...args: [...NewParams, ...array.Slice]) => R 28 | : never 29 | 30 | export type { Noop, GetAsyncFunctionReturnType, GetFunctionLength, Bind } 31 | -------------------------------------------------------------------------------- /documents/.vuepress/public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 8 | -------------------------------------------------------------------------------- /test/object.test.ts: -------------------------------------------------------------------------------- 1 | import { object } from ".."; 2 | 3 | interface O { 4 | item: 1; 5 | value: 2; 6 | id: "3"; 7 | } 8 | 9 | type ResultKeysToUnion = object.KeysToUnion; 10 | 11 | type ResultValues = object.Values; 12 | 13 | type ResultKeysToTuple = object.KeysToTuple; 14 | 15 | type ResultExtractValues = object.ExtractValues; 16 | 17 | type ResultExcludeValues = object.ExcludeValues; 18 | 19 | type ResultGetterSetterPrefix = object.GetterSetterPrefix; 20 | 21 | type ResultProxify = object.Proxify; 22 | 23 | type ResultNullableValue = object.NullableValue; 24 | 25 | type ResultInclude = object.Include; 26 | 27 | type ResultChangeRecordType = object.ChangeRecordType; 28 | 29 | interface ReadOnlyO { 30 | readonly value: 0; 31 | readonly item: 1; 32 | } 33 | 34 | type ResultMutable = object.Mutable; 35 | 36 | type ResultReadonlyPartial = object.ReadonlyPartial; 37 | 38 | type ResultDeepPartial = object.DeepPartial; 39 | 40 | interface DeepO { 41 | a: { 42 | b: { 43 | c: {}; 44 | d: 1; 45 | }; 46 | e: 1; 47 | }; 48 | f: { 49 | g: null; 50 | }; 51 | } 52 | 53 | type ResultChainedAccessUnion = object.ChainedAccessUnion; 54 | 55 | type ResultObjectToUnion = object.ObjectToUnion<{ 56 | a: 1 57 | b: 2 58 | c: 3 59 | }> 60 | 61 | export type { 62 | ResultKeysToUnion, 63 | ResultGetterSetterPrefix, 64 | ResultValues, 65 | ResultKeysToTuple, 66 | ResultExtractValues, 67 | ResultExcludeValues, 68 | ResultProxify, 69 | ResultNullableValue, 70 | ResultInclude, 71 | ResultChangeRecordType, 72 | ResultMutable, 73 | ResultReadonlyPartial, 74 | ResultDeepPartial, 75 | ResultChainedAccessUnion, 76 | ResultObjectToUnion 77 | }; 78 | -------------------------------------------------------------------------------- /test/string.test.ts: -------------------------------------------------------------------------------- 1 | import * as string from "../lib/string" 2 | 3 | type ResultIncludes = string.Includes<"呵哈", "1"> 4 | 5 | type ResultStringify = string.Stringify<1n> 6 | 7 | type ResultGetChars = string.GetChars<""> 8 | 9 | type ResultSplit = string.Split<"1,2,3", ","> 10 | 11 | type ResultStartsWidth = string.StartsWith<"123", "12"> 12 | 13 | type ResultEndsWidth = string.EndsWith<"123", ""> 14 | 15 | type ResultIndexOf = string.IndexOf<"123123", "1"> 16 | 17 | type ResultLastIndexOf = string.LastIndexOf<"123123", "1"> 18 | 19 | type ResultReplace = string.Replace<"我讨厌你", "讨厌", "爱"> 20 | 21 | type ResultReplaceAll = string.ReplaceAll<"想见你想见你只想见你", "你", "我"> 22 | 23 | type ResultRepeat = string.Repeat<"❤️", 8> 24 | 25 | type ResultPadStart = string.PadStart<"前面有空格", 6> 26 | 27 | type ResultPadEnd = string.PadStart<"后面有空格", 6> 28 | 29 | type ResultTrimLeft = string.TrimLeft<" 前面没有空格"> 30 | 31 | type ResultTrimRight = string.TrimRight<"后面没有空格 "> 32 | 33 | type ResultTrim = string.Trim<" 两边没有空格 "> 34 | 35 | type ResultCharAt = string.CharAt<"123", 2> 36 | 37 | type ResultToUpperCase = string.ToUpperCase<"abc"> 38 | 39 | type ResultToLowerCase = string.ToLowerCase<"ABC"> 40 | 41 | type ResultSubString = string.SubString<"1234", 1, 1> 42 | 43 | type ResultSubStr = string.SubStr<"1234", 1, 1> 44 | 45 | export type { 46 | ResultIncludes, 47 | ResultStringify, 48 | ResultGetChars, 49 | ResultSplit, 50 | ResultCharAt, 51 | ResultSubString, 52 | ResultSubStr, 53 | ResultStartsWidth, 54 | ResultEndsWidth, 55 | ResultIndexOf, 56 | ResultLastIndexOf, 57 | ResultReplace, 58 | ResultReplaceAll, 59 | ResultRepeat, 60 | ResultPadStart, 61 | ResultPadEnd, 62 | ResultTrimLeft, 63 | ResultTrimRight, 64 | ResultTrim, 65 | ResultToUpperCase, 66 | ResultToLowerCase, 67 | } 68 | -------------------------------------------------------------------------------- /test/array.test.ts: -------------------------------------------------------------------------------- 1 | import * as array from "../lib/array" 2 | 3 | type ResultGetArray = array.GetTuple<5> 4 | 5 | type ResultArraySet = array.ArraySet<[1, 2], 0, 0> 6 | 7 | type ResultTupleToUnion = array.TupleToUnion<[123, 456, "789", true]> 8 | 9 | type ResultPop = array.Pop<[1, 2, 3, 4]> 10 | 11 | type ResultShift = array.Shift<[1, 2, 3, 4]> 12 | 13 | type ResultUnShift = array.UnShift<[1, 2, 3, 4], 0> 14 | 15 | type ResultPush = array.Push<[1, 2, 3, 4], 5> 16 | 17 | type ResultConcat = array.Concat<[1, 2], [3, 4]> 18 | 19 | type ResultJoin = array.Join<[1, 2, 3], ","> 20 | 21 | type ResultEvery = array.Every<[1, 2, 3], number> 22 | 23 | type ResultSome = array.Some<[1], number> 24 | 25 | type ResultFill = array.Fill<[1, 2], 2> 26 | 27 | type ResultFilter = array.Filter<[1, 2, 3, "4"], string> 28 | 29 | type ResultMapWidthIndex = array.MapWidthIndex<[1, 2, 3, 4, 5]> 30 | 31 | type ResultReverse = array.Reverse<[1, 2, 3, 4, 5, 6]> 32 | 33 | type ResultFind = array.Find<[1, "2", "3", 4], string> 34 | 35 | type ResultFindLast = array.FindLast<[1, "2", "3", 4], string> 36 | 37 | type ResultFindIndex = array.FindIndex<[1, "2", "3", 4], string> 38 | 39 | type ResultFindLastIndex = array.FindLastIndex<[1, "2", "3", 4], string> 40 | 41 | type ResultFlat = array.Flat<[1, [2, [3], 4]]> 42 | 43 | type ResultIncludes = array.Includes<[1, 2, 3, "2"], string> 44 | 45 | type ResultSlice = array.Slice<[1, 2, 3], 0, 2> 46 | 47 | type ResultSort = array.Sort<[2, 1]> 48 | 49 | export type { 50 | ResultGetArray, 51 | ResultArraySet, 52 | ResultTupleToUnion, 53 | ResultPop, 54 | ResultShift, 55 | ResultUnShift, 56 | ResultPush, 57 | ResultConcat, 58 | ResultJoin, 59 | ResultEvery, 60 | ResultSome, 61 | ResultFill, 62 | ResultFilter, 63 | ResultMapWidthIndex, 64 | ResultReverse, 65 | ResultFind, 66 | ResultFindLast, 67 | ResultFindIndex, 68 | ResultFindLastIndex, 69 | ResultFlat, 70 | ResultIncludes, 71 | ResultSlice, 72 | ResultSort, 73 | } 74 | -------------------------------------------------------------------------------- /documents/document/4.function.md: -------------------------------------------------------------------------------- 1 | # function 工具类型 2 | 3 | [在 CodeSandBox 中尝试](https://codesandbox.io/s/typescript-lodash-example-1l5hn?file=/src/function.ts) 4 | 5 | 注意:`function` 为 js 关键字,导入时,请自行起别名 6 | 7 | ## Noop 普通函数类型 8 | 9 | 普通函数类型 10 | 11 | **用于约束其他类型** 12 | 13 | ```ts 14 | type Noop = (...args: any) => any 15 | ``` 16 | 17 | ## GetAsyncFunctionReturnType 异步函数返回值 18 | 19 | 获取异步函数返回值 20 | 21 | **泛型参数** 22 | 23 | + F 24 | - 约束 `Noop` 25 | - 必须 `是` 26 | 27 | **示例** 28 | 29 | ```ts 30 | import * as t from "typescript-lodash" 31 | 32 | const request = async () => { 33 | return { 34 | code: 0, 35 | success: true, 36 | data: [] 37 | } 38 | } 39 | 40 | type Result = t.function.GetAsyncFunctionReturnType // { code: number; success: boolean; data: never[] } 41 | ``` 42 | 43 | ## GetFunctionLength 函数类型长度 44 | 45 | 获取函数类型参数的个数 46 | 47 | **泛型参数** 48 | 49 | + F 50 | - 约束 `Noop` 51 | - 必须 `是` 52 | 53 | **示例** 54 | 55 | ```ts 56 | import * as t from "typescript-lodash" 57 | 58 | const request = async () => { 59 | return { 60 | code: 0, 61 | success: true, 62 | data: [] 63 | } 64 | } 65 | 66 | type Result = t.function.GetFunctionLength // 1 67 | ``` 68 | 69 | ## Bind 修改 this 70 | 71 | 获取函数类型 this 类型和参数类型 72 | 73 | **泛型参数** 74 | 75 | + F 76 | - 约束 `Noop` 77 | - 必须 `是` 78 | 79 | + NewThisType 80 | - 约束 `any` 81 | - 必须 `否` 82 | - 默认 `null` 83 | - 注:新的 this 类型 84 | 85 | + NewParams 86 | - 约束 `unknown[]` 87 | - 必须 `否` 88 | - 默认 `[]` 89 | - 注:新的参数类型,长度应小于等于旧参数类型 90 | 91 | **示例** 92 | 93 | ```ts 94 | import * as t from "typescript-lodash" 95 | 96 | const request = async (id: number) => { 97 | return { 98 | code: 0, 99 | success: true, 100 | data: [] 101 | } 102 | } 103 | 104 | type Result = t.function.Bind // (this: GlobalThis, arg_0: string): void 105 | ``` 106 | 107 | -------------------------------------------------------------------------------- /documents/.vuepress/sidebar.js: -------------------------------------------------------------------------------- 1 | const path = require("path") 2 | const fs = require("fs") 3 | 4 | const nav = [ 5 | { text: "首页", link: "/" }, 6 | { text: "指南", link: "/guide/介绍.html" }, 7 | { text: "文档", link: "/document/1.number.html" }, 8 | { 9 | text: "原理", 10 | link: "https://juejin.cn/post/7061556434692997156", 11 | target: "_blank", 12 | }, 13 | { 14 | text: "npm", 15 | link: "https://www.npmjs.com/package/typescript-lodash", 16 | target: "_blank", 17 | }, 18 | { 19 | text: "github", 20 | link: "https://github.com/kawayiLinLin/typescript-lodash", 21 | target: "_blank", 22 | }, 23 | ] 24 | 25 | let sideBarConfigArr = [] 26 | function generateSideBar(pathline, sideBarConfig, url, item) { 27 | // 获取路径下的所有文件和文件夹名称 28 | let mdDirs = fs.readdirSync(pathline) 29 | const hasReadme = mdDirs.some((e) => e.includes("README")) 30 | mdDirs = mdDirs.filter((dir) => !dir.startsWith(".")) 31 | 32 | // 如果当前目录没有readme 需要删掉父级path属性 33 | if (!hasReadme) { 34 | delete item.path 35 | } 36 | 37 | // 遍历 38 | mdDirs.forEach((dir) => { 39 | // 获取当前文件或文件夹路径 40 | const fullpath = path.resolve(pathline, dir) 41 | const stats = fs.statSync(fullpath) 42 | 43 | // 如果是文件夹继续递归 44 | if (stats.isDirectory()) { 45 | const item = { 46 | title: dir, 47 | path: `${url}/${dir}/`.replace(/\/+/g, "/"), 48 | children: [], 49 | } 50 | generateSideBar( 51 | path.resolve(pathline, dir), 52 | item.children, 53 | `${url}/${dir}/`.replace(/\/+/g, "/"), 54 | item 55 | ) 56 | sideBarConfig.push(item) 57 | // 如果是个文件 58 | } else if (stats.isFile()) { 59 | // 如果是readme 60 | if (dir.includes("README")) { 61 | // sideBarConfig.push(url) 62 | } else { 63 | sideBarConfig.push(`${url}/${dir}`.replace(/\/+/g, "/")) 64 | } 65 | } 66 | }) 67 | } 68 | generateSideBar( 69 | path.resolve(__dirname, "../../documents"), 70 | sideBarConfigArr, 71 | "" 72 | ) 73 | 74 | // 单独处理最顶层分类 75 | sideBarConfigArr = sideBarConfigArr.reduce( 76 | (config, item) => ((config[item.path] = item.children), config), 77 | {} 78 | ) 79 | 80 | module.exports = { 81 | sidebar: sideBarConfigArr, 82 | nav, 83 | } 84 | -------------------------------------------------------------------------------- /lib/object.ts: -------------------------------------------------------------------------------- 1 | import { common } from ".." 2 | 3 | type KeysToTuple = KeysToUnion[] 4 | 5 | type KeysToUnion = keyof T 6 | 7 | type Values = T[KeysToUnion] 8 | 9 | type ExtractValues = { 10 | [Key in keyof T as T[Key] extends V ? Key : never]: T[Key] 11 | } 12 | 13 | type ExcludeValues = { 14 | [Key in keyof T as T[Key] extends V ? never : Key]: T[Key] 15 | } 16 | 17 | type GetterSetterPrefix = { 18 | [Key in keyof T as Key extends string ? `get${Capitalize}` : never]: { 19 | (): T[Key] 20 | } 21 | } & { 22 | [Key in keyof T as Key extends string ? `set${Capitalize}` : never]: { 23 | (val: T[Key]): void 24 | } 25 | } & T 26 | 27 | type Proxify = { 28 | [P in keyof T]: { 29 | get(): T[P] 30 | set(v: T[P]): void 31 | } 32 | } 33 | 34 | type NullableValue = { 35 | [Key in keyof T]?: common.Nullable 36 | } 37 | 38 | type Include = { 39 | [Key in keyof T as Key extends U ? Key : never]: T[Key] 40 | } 41 | 42 | type ChangeRecordType = { 43 | [P in keyof K]?: T 44 | } 45 | 46 | type Mutable = { 47 | -readonly [P in keyof T]: T[P] 48 | } 49 | 50 | type ReadonlyPartial = { 51 | readonly [P in keyof T]?: T[P] 52 | } 53 | 54 | type DeepPartial = { 55 | [Key in keyof T]?: T[Key] extends object ? DeepPartial : T[Key] 56 | } 57 | 58 | type ChainedAccessUnion = ChainedAccessUnionHelper 59 | 60 | type ChainedAccessUnionHelper< 61 | T, 62 | A = { 63 | [Key in keyof T]: T[Key] extends string ? never : T[Key] 64 | }, 65 | B = { 66 | [Key in keyof A]: A[Key] extends never 67 | ? never 68 | : A[Key] extends object 69 | ? 70 | | `${Extract}.${Extract}` 71 | | (ChainedAccessUnionHelper extends infer U 72 | ? `${Extract}.${Extract}` 73 | : never) 74 | : never 75 | } 76 | > = T extends object 77 | ? Exclude, never>, never> 78 | : never 79 | 80 | /** 81 | * @see https://juejin.cn/post/7164407257151569956 82 | */ 83 | type ObjectToUnion = Values<{ 84 | [Key in keyof T]: { 85 | [Current in Key]: T[Current] 86 | } 87 | }> 88 | 89 | export type { 90 | KeysToTuple, 91 | KeysToUnion, 92 | Values, 93 | ChainedAccessUnion, 94 | ExtractValues, 95 | ExcludeValues, 96 | GetterSetterPrefix, 97 | Proxify, 98 | NullableValue, 99 | Include, 100 | ChangeRecordType, 101 | DeepPartial, 102 | ReadonlyPartial, 103 | Mutable, 104 | ObjectToUnion, 105 | } 106 | -------------------------------------------------------------------------------- /lib/common.ts: -------------------------------------------------------------------------------- 1 | type Not = C extends true ? false : true 2 | 3 | type And = C1 extends true 4 | ? C2 extends true 5 | ? true 6 | : false 7 | : false 8 | 9 | type And3 = And< 10 | And, 11 | C3 12 | > 13 | 14 | type And4< 15 | C1 extends boolean, 16 | C2 extends boolean, 17 | C3 extends boolean, 18 | C4 extends boolean 19 | > = And, C4> 20 | 21 | type Or = C1 extends true 22 | ? true 23 | : C2 extends true 24 | ? true 25 | : false 26 | 27 | type Or3 = Or< 28 | Or, 29 | C3 30 | > 31 | 32 | type Or4< 33 | C1 extends boolean, 34 | C2 extends boolean, 35 | C3 extends boolean, 36 | C4 extends boolean 37 | > = Or, C4> 38 | 39 | type CheckLeftIsExtendsRight = T extends R 40 | ? true 41 | : false 42 | 43 | /** 44 | * @see https://github.com/microsoft/TypeScript/issues/27024#issuecomment-510924206 45 | * @description 判断类型严格相等 46 | */ 47 | type IsEqual = (() => T extends A ? 1 : 2) extends < 48 | T1 49 | >() => T1 extends B ? 1 : 2 50 | ? true 51 | : false 52 | 53 | type IsAny = 0 extends 1 & T ? true : false 54 | 55 | type IsNever = [T] extends [never] ? true : false 56 | 57 | type IsUnion = A extends A ? ([B] extends [A] ? false : true) : never 58 | 59 | type SafeCheck = T extends null | undefined | never ? false : true 60 | 61 | type Diff = Exclude | Exclude 62 | 63 | type SumAggregate = T | U 64 | 65 | type Nullable = T | null | undefined 66 | 67 | type Many = T | T[] 68 | 69 | /** 70 | * @see https://juejin.cn/book/7047524421182947366/section/7048282437238915110#UnionToIntersection 71 | * @description 联合类型转交叉类型 72 | * 73 | * 分布式条件类型 + 函数参数的逆变进行实现 74 | */ 75 | type UnionToIntersection = ( 76 | U extends U ? (x: U) => unknown : never 77 | ) extends (x: infer R) => unknown 78 | ? R 79 | : never 80 | 81 | /** 82 | * @see https://juejin.cn/book/7047524421182947366/section/7061543892180533283#UnionToTuple 83 | * @description 联合类型转元组 84 | * 85 | * 通过函数交叉类型进行重载、重载函数返回值类型为最后一个的特点,结合UnionToIntersection实现 86 | */ 87 | type UnionToTuple = UnionToIntersection< 88 | T extends any ? () => T : never 89 | > extends () => infer ReturnType 90 | ? [...UnionToTuple>, ReturnType] 91 | : [] 92 | 93 | export type { 94 | Not, 95 | And, 96 | And3, 97 | And4, 98 | IsAny, 99 | IsNever, 100 | Or, 101 | Or3, 102 | Or4, 103 | CheckLeftIsExtendsRight, 104 | IsEqual, 105 | SafeCheck, 106 | Diff, 107 | SumAggregate, 108 | Nullable, 109 | Many, 110 | UnionToIntersection, 111 | UnionToTuple, 112 | IsUnion 113 | } 114 | -------------------------------------------------------------------------------- /documents/document/6.common.md: -------------------------------------------------------------------------------- 1 | # common 工具类型 2 | 3 | [在 CodeSandBox 中尝试](https://codesandbox.io/s/typescript-lodash-example-1l5hn?file=/src/common.ts) 4 | 5 | ## And 与 6 | 7 | 求出两个布尔类型进行逻辑与的结果 8 | 9 | **泛型参数** 10 | 11 | + C1 12 | - 约束 `boolean` 13 | - 必须 `是` 14 | 15 | + C2 16 | - 约束 `boolean` 17 | - 必须 `是` 18 | 19 | **示例** 20 | 21 | ```ts 22 | import { common } from "typescript-lodash" 23 | 24 | type Result1 = common.And // true 25 | 26 | type Result2 = common.And // false 27 | 28 | type Result3 = common.And // false 29 | 30 | type Result4 = common.And // false 31 | 32 | // 你可以使用 common.And3 和 common.And4 进行多个布尔类型的计算 33 | ``` 34 | 35 | ## Or 或 36 | 37 | 求出两个布尔类型进行逻辑或的结果 38 | 39 | **泛型参数** 40 | 41 | + C1 42 | - 约束 `boolean` 43 | - 必须 `是` 44 | 45 | + C2 46 | - 约束 `boolean` 47 | - 必须 `是` 48 | 49 | **示例** 50 | 51 | ```ts 52 | import { common } from "typescript-lodash" 53 | 54 | type Result1 = common.Or // true 55 | 56 | type Result2 = common.Or // true 57 | 58 | type Result3 = common.Or // true 59 | 60 | type Result4 = common.Or // false 61 | 62 | // 你可以使用 common.Or3 和 common.Or4 进行多个布尔类型的计算 63 | ``` 64 | 65 | ## Not 非 66 | 67 | 求出布尔类型进行逻辑非的结果 68 | 69 | **泛型参数** 70 | 71 | + C 72 | - 约束 `boolean` 73 | - 必须 `是` 74 | 75 | **示例** 76 | 77 | ```ts 78 | import { common } from "typescript-lodash" 79 | 80 | type Result1 = common.Not // true 81 | 82 | type Result2 = common.Not // false 83 | ``` 84 | 85 | ## CheckLeftIsExtendsRight 约束校验 86 | 87 | 校验左侧类型是否满足右侧类型的约束 88 | 89 | 如果是,则得到 `true`,否则得到 `false` 90 | 91 | **泛型参数** 92 | 93 | + T 94 | - 约束 `any` 95 | - 必须 `是` 96 | 97 | + R 98 | - 约束 `any` 99 | - 必须 `是` 100 | 101 | **示例** 102 | 103 | ```ts 104 | import { common } from "typescript-lodash" 105 | 106 | type Result1 = common.CheckLeftIsExtendsRight<1, number> // true 107 | 108 | type Result2 = common.CheckLeftIsExtendsRight<1, any> // true 109 | 110 | type Result3 = common.CheckLeftIsExtendsRight<1, 2> // false 111 | ``` 112 | 113 | ## IsEqual 类型相等 114 | 115 | 判断两个类型是否严格相等 116 | 117 | 如果是,则得到 `true`,否则得到 `false` 118 | 119 | **泛型参数** 120 | 121 | + T 122 | - 约束 `any` 123 | - 必须 `是` 124 | 125 | + R 126 | - 约束 `any` 127 | - 必须 `是` 128 | 129 | **示例** 130 | 131 | ```ts 132 | import { common } from "typescript-lodash" 133 | 134 | type Result1 = common.IsEqual<1, number> // false 135 | 136 | type Result2 = common.IsEqual<1, 1> // true 137 | 138 | type Result3 = common.IsEqual<1, any> // false 139 | ``` 140 | 141 | ## IsAny 判断 any 142 | 143 | 判断当前类型是否为 any 144 | 145 | 如果是,则得到 `true`,否则得到 `false` 146 | 147 | **泛型参数** 148 | 149 | + T 150 | - 约束 `any` 151 | - 必须 `是` 152 | 153 | **示例** 154 | 155 | ```ts 156 | import { common } from "typescript-lodash" 157 | 158 | type Result1 = common.IsAny // false 159 | 160 | type Result2 = common.IsAny // true 161 | ``` 162 | 163 | ## IsNever 判断 never 164 | 165 | 判断当前类型是否为 never 166 | 167 | 如果是,则得到 `true`,否则得到 `false` 168 | 169 | **泛型参数** 170 | 171 | + T 172 | - 约束 `any` 173 | - 必须 `是` 174 | 175 | **示例** 176 | 177 | ```ts 178 | import { common } from "typescript-lodash" 179 | 180 | type Result1 = common.IsNever // true 181 | 182 | type Result2 = common.IsNever<1> // false 183 | ``` 184 | 185 | ## IsUnion 判断联合类型 186 | 187 | 判断当前类型是否为联合类型 188 | 189 | 如果是,则得到 `true`,否则得到 `false` 190 | 191 | **泛型参数** 192 | 193 | + T 194 | - 约束 `any` 195 | - 必须 `是` 196 | 197 | **示例** 198 | 199 | ```ts 200 | import { common } from "typescript-lodash" 201 | 202 | type Result1 = common.IsUnion<1 | 2> // true 203 | 204 | type Result2 = common.IsUnion<1> // false 205 | ``` 206 | 207 | ## Diff 差异 208 | 209 | 求两个联合类型的差异 210 | 211 | **泛型参数** 212 | 213 | + T 214 | - 约束 `any` 215 | - 必须 `是` 216 | 217 | + C 218 | - 约束 `any` 219 | - 必须 `是` 220 | 221 | **示例** 222 | 223 | ```ts 224 | import { common } from "typescript-lodash" 225 | 226 | type Result1 = common.Diff<1 | 2, 1 | 3> // 2 | 3 227 | 228 | type Result2 = common.Diff<1 | 2, 1 | 2> // never 229 | ``` 230 | 231 | 232 | ## SumAggregate 并集 233 | 234 | 求两个联合类型的并集 235 | 236 | **泛型参数** 237 | 238 | + T 239 | - 约束 `any` 240 | - 必须 `是` 241 | 242 | + C 243 | - 约束 `any` 244 | - 必须 `是` 245 | 246 | **示例** 247 | 248 | ```ts 249 | import { common } from "typescript-lodash" 250 | 251 | type Result1 = common.SumAggregate<1 | 2, 1 | 3> // 1 | 2 | 3 252 | ``` 253 | 254 | ## Nullable 可为空 255 | 256 | 将类型变为可以为空的类型 257 | 258 | **泛型参数** 259 | 260 | + T 261 | - 约束 `any` 262 | - 必须 `是` 263 | 264 | **示例** 265 | 266 | ```ts 267 | import { common } from "typescript-lodash" 268 | 269 | type Result1 = common.Nullable<1 | 2> // 1 | 2 | null | undefined 270 | ``` 271 | 272 | ## Many 一个或若干个 273 | 274 | 将类型变为可为数组的联合类型 275 | 276 | **泛型参数** 277 | 278 | + T 279 | - 约束 `any` 280 | - 必须 `是` 281 | 282 | **示例** 283 | 284 | ```ts 285 | import { common } from "typescript-lodash" 286 | 287 | type Result1 = common.Many // string | string[] 288 | ``` 289 | 290 | ## UnionToIntersection 联合转交叉 291 | 292 | 将联合类型变为交叉类型 293 | 294 | **泛型参数** 295 | 296 | + U 297 | - 约束 `any` 298 | - 必须 `是` 299 | 300 | **示例** 301 | 302 | ```ts 303 | import { common } from "typescript-lodash" 304 | 305 | type Result1 = common.UnionToIntersection<{ a: 1 } | { b: 1 }> // { a: 1 } & { b: 1 } 306 | ``` 307 | 308 | 309 | ## UnionToTuple 联合转元组 310 | 311 | 将联合类型变为元组类型 312 | 313 | **泛型参数** 314 | 315 | + U 316 | - 约束 `any` 317 | - 必须 `是` 318 | 319 | **示例** 320 | 321 | ```ts 322 | import { common } from "typescript-lodash" 323 | 324 | type Result1 = common.UnionToTuple<1 | 2 | 3> // [1, 2, 3] 325 | ``` -------------------------------------------------------------------------------- /documents/document/5.object.md: -------------------------------------------------------------------------------- 1 | # object 工具类型 2 | 3 | [在 CodeSandBox 中尝试](https://codesandbox.io/s/typescript-lodash-example-1l5hn?file=/src/object.ts) 4 | 5 | ## KeysToUnion 键转联合类型 6 | 7 | 将对象类型的键转为联合类型 8 | 9 | **泛型参数** 10 | 11 | + T 12 | - 约束 `any` 13 | - 必须 `是` 14 | 15 | **示例** 16 | 17 | ```ts 18 | import { object } from 'typescript-lodash' 19 | 20 | interface O { 21 | item: 1 22 | value: 2 23 | id: 3 24 | } 25 | 26 | type Result = object.KeysToUnion // 'item' | 'value' | 'id' 27 | ``` 28 | 29 | ## Values 值类型转联合类型 30 | 31 | 将对象类型的所有值的类型转为联合类型 32 | 33 | **泛型参数** 34 | 35 | + T 36 | - 约束 `any` 37 | - 必须 `是` 38 | 39 | **示例** 40 | 41 | ```ts 42 | import { object } from 'typescript-lodash' 43 | 44 | interface O { 45 | item: 1 46 | value: 2 47 | id: 3 48 | } 49 | 50 | type Result = object.Values // 1 | 2 | 3 51 | ``` 52 | 53 | ## KeysToTuple 键转元组 54 | 55 | 将对象类型的所有键的类型转为元组类型 56 | 57 | **泛型参数** 58 | 59 | + T 60 | - 约束 `any` 61 | - 必须 `是` 62 | 63 | **示例** 64 | 65 | ```ts 66 | import { object } from 'typescript-lodash' 67 | 68 | interface O { 69 | item: 1 70 | value: 2 71 | id: 3 72 | } 73 | 74 | type Result = object.KeysToTuple // ('item' | 'value' | 'id')[] 75 | ``` 76 | 77 | ## ExtractValues 过滤符合条件的属性 78 | 79 | 过滤出对象类型中属性值符合约束的属性 80 | 81 | **泛型参数** 82 | 83 | + T 84 | - 约束 `any` 85 | - 必须 `是` 86 | 87 | + V 88 | - 约束 `any` 89 | - 必须 `是` 90 | 91 | **示例** 92 | 93 | ```ts 94 | import { object } from 'typescript-lodash' 95 | 96 | interface O { 97 | item: 1 98 | value: 2 99 | id: '3' 100 | } 101 | 102 | type Result = object.ExtractValues // { item: 1; value: 2 } 103 | ``` 104 | 105 | ## ExcludeValues 过滤不符合条件的属性 106 | 107 | 过滤出对象类型中属性值不符合约束的属性 108 | 109 | **泛型参数** 110 | 111 | + T 112 | - 约束 `any` 113 | - 必须 `是` 114 | 115 | + V 116 | - 约束 `any` 117 | - 必须 `是` 118 | 119 | **示例** 120 | 121 | ```ts 122 | import { object } from 'typescript-lodash' 123 | 124 | interface O { 125 | item: 1 126 | value: 2 127 | id: '3' 128 | } 129 | 130 | type Result = object.ExcludeValues // { id: "3" } 131 | ``` 132 | 133 | ## GetterSetterPrefix 添加 get 和 set 前缀 134 | 135 | 为对象类型中的每个属性名添加 get 和 set 前缀 136 | 137 | **泛型参数** 138 | 139 | + T 140 | - 约束 `any` 141 | - 必须 `是` 142 | 143 | **示例** 144 | 145 | ```ts 146 | import { object } from 'typescript-lodash' 147 | 148 | interface O { 149 | item: 1 150 | } 151 | 152 | type Result = object.GetterSetterPrefix // { getItem: () => 1; setItem: (val: 1) => void; item: 1 } 153 | ``` 154 | 155 | ## Proxify 转为 get set 形式 156 | 157 | 将对象类型的每个属性值转为包含 get 和 set 的对象类型 158 | 159 | **泛型参数** 160 | 161 | + T 162 | - 约束 `any` 163 | - 必须 `是` 164 | 165 | **示例** 166 | 167 | ```ts 168 | import { object } from 'typescript-lodash' 169 | 170 | interface O { 171 | item: 1 172 | } 173 | 174 | type Result = object.Proxify // { item: { get: () => 1; set: (val: 1) => void } } 175 | ``` 176 | 177 | ## NullableValue 值可为空 178 | 179 | 将对象类型的每个属性值转为可为空 180 | 181 | **泛型参数** 182 | 183 | + T 184 | - 约束 `any` 185 | - 必须 `是` 186 | 187 | **示例** 188 | 189 | ```ts 190 | import { object } from 'typescript-lodash' 191 | 192 | interface O { 193 | item: 1 194 | } 195 | 196 | type Result = object.NullableValue // { item: null | undefined | 1 } 197 | ``` 198 | 199 | ## Include 提取键名符合条件的键 200 | 201 | 提取对象类型中,符合约束的键,并构造新类型 202 | 203 | **泛型参数** 204 | 205 | + T 206 | - 约束 `any` 207 | - 必须 `是` 208 | 209 | + U 210 | - 约束 `keyof any` 211 | - 必须 `是` 212 | 213 | **示例** 214 | 215 | ```ts 216 | import { object } from 'typescript-lodash' 217 | 218 | interface O { 219 | value: 0 220 | item: 1 221 | } 222 | 223 | type Result = object.Include // { value: 1 } 224 | ``` 225 | 226 | ## ChangeRecordType 填充类型 227 | 228 | 将对象类型的属性值填充为给定类型 229 | 230 | **泛型参数** 231 | 232 | + K 233 | - 约束 `any` 234 | - 必须 `是` 235 | 236 | + T 237 | - 约束 `any` 238 | - 必须 `否` 239 | - 默认 `undefined` 240 | - 注:用于填充的类型 241 | 242 | **示例** 243 | 244 | ```ts 245 | import { object } from 'typescript-lodash' 246 | 247 | interface O { 248 | value: 0 249 | item: 1 250 | } 251 | 252 | type Result = object.ChangeRecordType // { value: null; item: null } 253 | ``` 254 | 255 | ## Mutable 可写 256 | 257 | 将只读对象类型转为可写对象类型 258 | 259 | **泛型参数** 260 | 261 | + T 262 | - 约束 `any` 263 | - 必须 `是` 264 | 265 | **示例** 266 | 267 | ```ts 268 | import { object } from 'typescript-lodash' 269 | 270 | interface O { 271 | readonly value: 0 272 | readonly item: 1 273 | } 274 | 275 | type Result = object.Mutable // { value: 0; item: 1 } 276 | ``` 277 | 278 | ## ReadonlyPartial 只读且可选 279 | 280 | 将对象类型的属性转为只读但可选 281 | 282 | **泛型参数** 283 | 284 | + T 285 | - 约束 `any` 286 | - 必须 `是` 287 | 288 | **示例** 289 | 290 | ```ts 291 | import { object } from 'typescript-lodash' 292 | 293 | interface O { 294 | value: 0 295 | item: 1 296 | } 297 | 298 | type Result = object.ReadonlyPartial // { readonly value?: 0 | undefined; readonly item?: 1 | undefined } 299 | ``` 300 | 301 | ## DeepPartial 所有属性可选 302 | 303 | 将对象类型的所有属性转为可选 304 | 305 | **泛型参数** 306 | 307 | + T 308 | - 约束 `any` 309 | - 必须 `是` 310 | 311 | **示例** 312 | 313 | ```ts 314 | import { object } from 'typescript-lodash' 315 | 316 | interface O { 317 | value: 0 318 | item: 1 319 | } 320 | 321 | type Result = object.DeepPartial // { value?: 0 | undefined; item?: 1 | undefined } 322 | ``` 323 | 324 | ## ChainedAccessUnion 查找可读路径 325 | 326 | 将对象的所有可以访问的属性路径,以联合类型表示 327 | 328 | **泛型参数** 329 | 330 | + T 331 | - 约束 `any` 332 | - 必须 `是` 333 | 334 | **示例** 335 | 336 | ```ts 337 | import { object } from 'typescript-lodash' 338 | 339 | interface O { 340 | a: { 341 | b: { 342 | c: {} 343 | d: 1 344 | } 345 | e: 1 346 | } 347 | f: { 348 | g: null 349 | } 350 | } 351 | 352 | type Result = object.ChainedAccessUnion // "a" | "f" | "a.b" | "a.b.c" | "a.b.d" | "a.e" | "f.g" 353 | ``` 354 | 355 | ## ObjectToUnion 对象转元组 356 | 357 | 将对象类型转为联合类型 358 | 359 | **泛型参数** 360 | 361 | + T 362 | - 约束 `any` 363 | - 必须 `是` 364 | 365 | **示例** 366 | 367 | ```ts 368 | import { object } from 'typescript-lodash' 369 | 370 | interface O { 371 | a: 1 372 | b: 2 373 | } 374 | 375 | type Result = object.ObjectToUnion // { a: 1 } | { b: 2 } 376 | ``` -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Basic Options */ 6 | "incremental": true, /* Enable incremental compilation */ 7 | "target": "ESNEXT", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */ 8 | "module": "ESNEXT", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 9 | // "lib": [], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ 13 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | // "outDir": "./", /* Redirect output structure to the directory. */ 18 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 21 | // "removeComments": true, /* Do not emit comments to output. */ 22 | // "noEmit": true, /* Do not emit outputs. */ 23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 25 | "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 26 | 27 | /* Strict Type-Checking Options */ 28 | "strict": true, /* Enable all strict type-checking options. */ 29 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 30 | // "strictNullChecks": true, /* Enable strict null checks. */ 31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 36 | 37 | /* Additional Checks */ 38 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 42 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 43 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */ 44 | // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ 45 | 46 | /* Module Resolution Options */ 47 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 48 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 49 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 50 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 51 | // "typeRoots": [], /* List of folders to include type definitions from. */ 52 | // "types": [], /* Type declaration files to be included in compilation. */ 53 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 54 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 55 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 56 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 57 | 58 | /* Source Map Options */ 59 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 60 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 61 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 62 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 63 | 64 | /* Experimental Options */ 65 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 66 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 67 | 68 | /* Advanced Options */ 69 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 70 | "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ 71 | "noErrorTruncation": true 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /lib/string.ts: -------------------------------------------------------------------------------- 1 | import { number, array, common } from ".." 2 | 3 | type CanStringified = string | number | bigint | boolean | null | undefined 4 | 5 | /** 6 | * @exports 7 | * 将支持的类型转化为字符串 8 | */ 9 | type Stringify = `${T}` 10 | 11 | /** 12 | * @@exports 13 | * 获取模板字符串类型中的字符 14 | * @see https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html 15 | * @example 16 | * type Result = GetChars<'abc'> // 'a' | 'b' | 'c' 17 | */ 18 | type GetChars = GetCharsHelper 19 | 20 | /** 21 | * 以 尾递归 tail-recursive 的方式优化 GetChars,不导出为工具类型 22 | */ 23 | type GetCharsHelper = S extends `${infer Char}${infer Rest}` 24 | ? GetCharsHelper 25 | : Acc 26 | 27 | type SplitHelper< 28 | S extends string, 29 | SplitStr extends string = "", 30 | A extends string[] = [] 31 | > = S extends `${infer Char}${SplitStr}${infer Rest}` 32 | ? SplitHelper> 33 | : S extends string 34 | ? S extends "" 35 | ? A 36 | : array.Push 37 | : never 38 | 39 | /** 40 | * @exports 41 | * 拆分字符串变为一个元组 42 | */ 43 | type Split = SplitHelper< 44 | S, 45 | SplitStr 46 | > 47 | 48 | /** 49 | * @exports 50 | * 获取字符串的长度 51 | */ 52 | type GetStringLength = Split["length"] 53 | 54 | /** 55 | * @exports 56 | * 获取字符串在索引位 I 下的 字符 57 | */ 58 | type CharAt = Split[I] 59 | 60 | /** 61 | * @exports 62 | * 拼接两个字符串 63 | */ 64 | type Concat = `${S1}${S2}` 65 | 66 | /** 67 | * @exports 68 | * 判断字符串是否包含子串 69 | */ 70 | type Includes< 71 | S1 extends string, 72 | S2 extends string 73 | > = S1 extends `${infer Left}${S2}${infer Right}` ? true : false 74 | 75 | /** 76 | * @exports 77 | * 判断字符串是否以子串为起始 78 | */ 79 | type StartsWith< 80 | S1 extends string, 81 | S2 extends string 82 | > = S1 extends `${S2}${infer Right}` ? true : false 83 | 84 | /** 85 | * @exports 86 | * 判断字符串是否以子串为结束 87 | */ 88 | type EndsWith< 89 | S1 extends string, 90 | S2 extends string 91 | > = S1 extends `${infer Left}${S2}` ? true : false 92 | 93 | type IndexOfHelper< 94 | S1 extends string, 95 | S2 extends string, 96 | Len1 extends number = GetStringLength, 97 | Len2 extends number = GetStringLength 98 | > = common.Or< 99 | number.Compare, 100 | number.IsEqual 101 | > extends true 102 | ? S1 extends `${infer Left}${S2}${infer Right}` 103 | ? GetStringLength 104 | : -1 105 | : -1 106 | 107 | /** 108 | * @exports 109 | * 从左往右查找子串的位置 110 | */ 111 | type IndexOf = IndexOfHelper 112 | 113 | type LastIndexOfHelper< 114 | S1 extends string, 115 | S2 extends string, 116 | Index extends number = -1 /** 当前从左往右匹配最大的值,匹配不到以后,上一次匹配的索引就是从右往左第一个的索引 */, 117 | AddOffset extends number = 0 /** 累加的偏移量; 每次从左往右匹配成功后,将匹配到的字符串替换为S2.substring(1),且偏移量加1 */ 118 | > = S1 extends `${infer Left}${S2}${infer Right}` 119 | ? LastIndexOfHelper< 120 | Replace>>, 121 | S2, 122 | number.IntAddSimple, AddOffset>, 123 | number.IntAddSimple 124 | > 125 | : Index 126 | 127 | /** 128 | * @exports 129 | * 从右往左查找子串的位置 130 | */ 131 | type LastIndexOf = LastIndexOfHelper< 132 | S1, 133 | S2 134 | > 135 | 136 | /** 137 | * @exports 138 | * 在字符串中查找并替换一处子串 139 | */ 140 | type Replace< 141 | S extends string, 142 | MatchStr extends string, 143 | ReplaceStr extends string 144 | > = S extends `${infer Left}${MatchStr}${infer Right}` 145 | ? `${Left}${ReplaceStr}${Right}` 146 | : S 147 | 148 | /** 149 | * @exports 150 | * 在字符串中查找并替换所有子串 151 | */ 152 | type ReplaceAll< 153 | S extends string, 154 | MatchStr extends string, 155 | ReplaceStr extends string 156 | > = Includes extends true 157 | ? ReplaceAll, MatchStr, ReplaceStr> 158 | : S 159 | 160 | type RepeatHelper< 161 | S extends string, 162 | Times extends number, 163 | OriginStr extends string = S, 164 | Offset extends number = 1 165 | > = Times extends 0 166 | ? "" 167 | : number.IsEqual extends true 168 | ? S 169 | : `${OriginStr}${RepeatHelper< 170 | S, 171 | Times, 172 | OriginStr, 173 | number.IntAddSimple 174 | >}` 175 | 176 | /** 177 | * @exports 178 | * 重复 Times 次数的字符串 179 | */ 180 | type Repeat = RepeatHelper 181 | 182 | type PadHelper< 183 | S extends string, 184 | N extends number = 0, 185 | FillS extends string = " ", 186 | IsStart extends boolean = true, 187 | Len extends number = GetStringLength, 188 | Offset extends number = Len 189 | > = number.Compare extends true 190 | ? number.IsEqual extends true 191 | ? S 192 | : PadHelper< 193 | `${IsStart extends true ? FillS : ""}${S}${IsStart extends false 194 | ? FillS 195 | : ""}`, 196 | N, 197 | FillS, 198 | IsStart, 199 | Len, 200 | number.IntAddSimple 201 | > 202 | : S 203 | 204 | type PadStart< 205 | S extends string, 206 | N extends number = 0, 207 | FillS extends string = " " 208 | > = PadHelper 209 | 210 | type PadEnd< 211 | S extends string, 212 | N extends number = 0, 213 | FillS extends string = " " 214 | > = PadHelper 215 | 216 | /** 217 | * @see https://juejin.cn/post/7045536402112512007#heading-5 218 | */ 219 | type TrimLeft = S extends `${ 220 | | " " 221 | | "\t" 222 | | "\n"}${infer RightRest}` 223 | ? TrimLeft 224 | : S 225 | 226 | type TrimRight = S extends `${infer LeftRest}${ 227 | | " " 228 | | "\t" 229 | | "\n"}` 230 | ? TrimRight 231 | : S 232 | 233 | type Trim = TrimLeft> 234 | 235 | type ToUpperCase = Uppercase 236 | 237 | type ToLowerCase = Lowercase 238 | 239 | /** 240 | * 在字符串中抽取从 开始 下标开始的指定数目的字符 241 | */ 242 | type SubStr< 243 | S extends string, 244 | Start extends number, 245 | Len extends number 246 | > = SubStringHelper> 247 | 248 | type SubStringHelper< 249 | S extends string, 250 | Start extends number, 251 | End extends number, 252 | Offset extends number = 0, 253 | Cache extends string[] = [] 254 | > = number.IsEqual extends true 255 | ? array.Join 256 | : SubStringHelper< 257 | S, 258 | Start, 259 | End, 260 | number.IntAddSimple, 261 | common.And3< 262 | common.Or, number.IsEqual>, 263 | common.Or, number.IsEqual>, 264 | CharAt extends string ? true : false 265 | > extends true 266 | ? array.Push> 267 | : Cache 268 | > 269 | 270 | /** 271 | * 截取start(包括)到end(不包括)之间的字符串 272 | */ 273 | type SubString< 274 | S extends string, 275 | Start extends number, 276 | End extends number 277 | > = SubStringHelper 278 | 279 | export type { 280 | CanStringified, 281 | Stringify, 282 | GetChars, 283 | Split, 284 | GetStringLength, 285 | CharAt, 286 | Concat, 287 | Includes, 288 | StartsWith, 289 | EndsWith, 290 | IndexOf, 291 | LastIndexOf, 292 | Replace, 293 | ReplaceAll, 294 | Repeat, 295 | PadStart, 296 | PadEnd, 297 | TrimLeft, 298 | TrimRight, 299 | Trim, 300 | ToUpperCase, 301 | ToLowerCase, 302 | SubStr, 303 | SubString, 304 | } 305 | -------------------------------------------------------------------------------- /documents/document/1.number.md: -------------------------------------------------------------------------------- 1 | # number 工具类型 2 | 3 | [在 CodeSandBox 中尝试](https://codesandbox.io/s/typescript-lodash-example-1l5hn?file=/src/number.ts) 4 | 5 | ## NumberLike 形如数字类型 6 | 7 | 形如数字的类型,如:`0`、`"0"`、`0.1`、`-1`、`"-0.1"`、`"+1"` 等 8 | 9 | **用于约束其他类型** 10 | 11 | ```ts 12 | type NumberLike = `${number}` | number 13 | ``` 14 | 15 | ## IsZero 判断类型为 0 16 | 17 | 判断一个数字类型(或形如)是否为 `0` 18 | 19 | 如果是,则得到类型 `true`,否则得到类型 `false` 20 | 21 | **泛型参数** 22 | 23 | + N 24 | - 约束 `NumberLike` 25 | - 必须 `是` 26 | 27 | **示例** 28 | 29 | ```ts 30 | import { number } from 'typescript-lodash' 31 | 32 | type Result1 = number.IsZero<0> // true 33 | 34 | type Result2 = number.IsZero<"0"> // true 35 | 36 | type Result3 = number.IsZero<"0.0"> // false, 不能判断 "0.0" 的场景,但是数字类型的 0.0 和 -0 会得到 true 类型 37 | ``` 38 | 39 | ## IsNotZero 判断类型不为 0 40 | 41 | 判断一个数字类型(或形如)是否不为 `0` 42 | 43 | 如果是,则得到类型 `true`,否则得到类型 `false` 44 | 45 | **泛型参数** 46 | 47 | + N 48 | - 约束 `NumberLike` 49 | - 必须 `是` 50 | 51 | **示例** 52 | 53 | ```ts 54 | import { number } from 'typescript-lodash' 55 | 56 | type Result1 = number.IsNotZero<0> // false 57 | 58 | type Result2 = number.IsNotZero<"0"> // false 59 | 60 | type Result3 = number.IsNotZero<0.1> // true 61 | 62 | type Result4 = number.IsNotZero<-1> // true 63 | ``` 64 | 65 | ## IsOverZero 判断类型大于 0 66 | 67 | 判断一个数字类型(或形如)是否大于 `0` 68 | 69 | 如果是,则得到类型 `true`,否则得到类型 `false` 70 | 71 | **泛型参数** 72 | 73 | + N 74 | - 约束 `NumberLike` 75 | - 必须 `是` 76 | 77 | **示例** 78 | 79 | ```ts 80 | import { number } from 'typescript-lodash' 81 | 82 | type Result1 = number.IsOverZero<0> // false 83 | 84 | type Result2 = number.IsOverZero<-0.1> // false 85 | 86 | type Result3 = number.IsOverZero<'1'> // true 87 | 88 | type Result4 = number.IsOverZero<'+1'> // true 89 | ``` 90 | 91 | ## IsLessZero 判断类型小于 0 92 | 93 | 判断一个数字类型(或形如)是否小于 `0` 94 | 95 | 如果是,则得到类型 `true`,否则得到类型 `false` 96 | 97 | **泛型参数** 98 | 99 | + N 100 | - 约束 `NumberLike` 101 | - 必须 `是` 102 | 103 | **示例** 104 | 105 | ```ts 106 | import { number } from 'typescript-lodash' 107 | 108 | type Result1 = number.IsLessZero<0> // false 109 | 110 | type Result2 = number.IsLessZero<'1'> // false 111 | 112 | type Result3 = number.IsLessZero<'+1'> // false 113 | 114 | type Result3 = number.IsLessZero<'-1'> // true 115 | ``` 116 | 117 | ## IsFloat 判断类型为浮点型 118 | 119 | 判断一个数字类型(或形如)是否为浮点型 120 | 121 | 如果是,则得到类型 `true`,否则得到类型 `false` 122 | 123 | **泛型参数** 124 | 125 | + N 126 | - 约束 `NumberLike` 127 | - 必须 `是` 128 | 129 | + OnlyCheckPoint 130 | - 约束 `boolean` 131 | - 必须 `否` 132 | - 默认 `true` 133 | - 注:关闭后,如果小数位全是 0,则会得到 `false` 134 | 135 | **示例** 136 | 137 | ```ts 138 | import { number } from 'typescript-lodash' 139 | 140 | type Result1 = number.IsFloat<0> // false 141 | 142 | type Result2 = number.IsFloat<0.0> // false,数字类型 0.0 会得到 false,但字符类型 "0.0" 会得到 true 143 | 144 | type Result3 = number.IsFloat<'1'> // false 145 | 146 | type Result4 = number.IsFloat<1.1> // true 147 | 148 | type Result5 = number.IsFloat<1.0, false> // false 149 | 150 | type Result6 = number.IsFloat<1.0, true> // true 151 | ``` 152 | 153 | ## IsInt 判断类型为整型 154 | 155 | 判断一个数字类型(或形如)是否为整型 156 | 157 | 如果是,则得到类型 `true`,否则得到类型 `false` 158 | 159 | **泛型参数** 160 | 161 | + N 162 | - 约束 `NumberLike` 163 | - 必须 `是` 164 | 165 | + OnlyCheckPoint 166 | - 约束 `boolean` 167 | - 必须 `否` 168 | - 默认 `true` 169 | - 注:关闭后,如果小数位全是 0,则会得到 `true` 170 | 171 | **示例** 172 | 173 | ```ts 174 | import { number } from 'typescript-lodash' 175 | 176 | type Result1 = number.IsInt<0> // true 177 | 178 | type Result2 = number.IsInt<0.0> // true,数字类型 0.0 会得到 true,但字符类型 "0.0" 会得到 false 179 | 180 | type Result3 = number.IsInt<'1'> // true 181 | 182 | type Result4 = number.IsInt<1.1> // false 183 | 184 | type Result5 = number.IsInt<1.0, false> // true 185 | 186 | type Result6 = number.IsInt<1.0, true> // false 187 | ``` 188 | 189 | ## IsEqual 判断数字类型相等 190 | 191 | 判断两个数字类型(或形如)是否相等 192 | 193 | 如果是,则得到类型 `true`,否则得到类型 `false` 194 | 195 | **泛型参数** 196 | 197 | + L 198 | - 约束 `NumberLike` 199 | - 必须 `是` 200 | - 注:作为被约束的类型进行校验 201 | 202 | + R 203 | - 约束 `NumberLike` 204 | - 必须 `是` 205 | - 注:作为约束 206 | 207 | + Strict 208 | - 约束 `boolean` 209 | - 必须 `否` 210 | - 默认 `true` 211 | - 注:关闭后,形如数字类型和数字类型进行比较时,都转为字符串后相同,则会得到 `true` 212 | 213 | **示例** 214 | 215 | ```ts 216 | import { number } from 'typescript-lodash' 217 | 218 | type Result1 = number.IsEqual<0, 0> // true 219 | 220 | type Result2 = number.IsEqual<0, '0'> // false 221 | 222 | type Result3 = number.IsEqual<0, '0', false> // true 223 | 224 | type Result4 = number.IsEqual<0.1, '0.1', false> // true 225 | ``` 226 | 227 | ## IsNotEqual 数字类型是否不相等 228 | 229 | 判断两个数字类型(或形如)是否不相等 230 | 231 | 如果是,则得到类型 `true`,否则得到类型 `false` 232 | 233 | **泛型参数** 234 | 235 | + L 236 | - 约束 `NumberLike` 237 | - 必须 `是` 238 | - 注:作为被约束的类型进行校验 239 | 240 | + R 241 | - 约束 `NumberLike` 242 | - 必须 `是` 243 | - 注:作为约束 244 | 245 | + Strict 246 | - 约束 `boolean` 247 | - 必须 `否` 248 | - 默认 `true` 249 | - 注:关闭后,形如数字类型和数字类型进行比较时,都转为字符串后不相同,则会得到 `true` 250 | 251 | **示例** 252 | 253 | ```ts 254 | import { number } from 'typescript-lodash' 255 | 256 | type Result1 = number.IsNotEqual<0, 0> // false 257 | 258 | type Result2 = number.IsNotEqual<0, '0'> // true 259 | 260 | type Result3 = number.IsNotEqual<0, '0', false> // false 261 | 262 | type Result4 = number.IsNotEqual<0.1, 1> // true 263 | ``` 264 | 265 | ## IntIncrease 数字类型自增 266 | 267 | 返回一个形如数字类型加一的整数类型结果 268 | 269 | **泛型参数** 270 | 271 | + N 272 | - 约束 `NumberLike` 273 | - 必须 `是` 274 | 275 | **示例** 276 | 277 | ```ts 278 | import { number } from 'typescript-lodash' 279 | 280 | type Result1 = number.IntIncrease<99> // 100 281 | 282 | type Result2 = number.IntIncrease<0> // 1 283 | ``` 284 | 285 | ## IntAddSimple 数字类型相加 286 | 287 | 两个数字类型相加,得到新的数字类型(两数的和) 288 | 289 | ::: warning 注意 290 | 该数字类型相加工具类型有较为明显的边界限制 291 | ::: 292 | 293 | **泛型参数** 294 | 295 | + N1 296 | - 约束 `number` 297 | - 必须 `是` 298 | - 注:必须是大于等于0的整数,且不超过999 299 | 300 | + N2 301 | - 约束 `number` 302 | - 必须 `是` 303 | - 注:必须是大于等于0的整数,且不超过999 304 | 305 | **示例** 306 | 307 | ```ts 308 | import { number } from 'typescript-lodash' 309 | 310 | type Result1 = number.IntAddSimple<1, 2> // 3 311 | 312 | type Result2 = number.IntAddSimple<0, 1> // 1 313 | ``` 314 | 315 | ## Compare 比较类型大小 316 | 317 | 两个数字类型比较大小 318 | 319 | 如果第一个数字类型大于第二个数字类型,则得到 `true`,否则得到 `false` 320 | 321 | ::: warning 注意 322 | 该数字类型大小比较工具类型有较为明显的边界限制 323 | ::: 324 | 325 | **泛型参数** 326 | 327 | + N1 328 | - 约束 `number` 329 | - 必须 `是` 330 | - 注:必须是大于等于0的整数,且不超过999 331 | 332 | + N2 333 | - 约束 `number` 334 | - 必须 `是` 335 | - 注:必须是大于等于0的整数,且不超过999 336 | 337 | **示例** 338 | 339 | ```ts 340 | import { number } from 'typescript-lodash' 341 | 342 | type Result1 = number.Compare<1, 1> // false 343 | 344 | type Result2 = number.Compare<0, 1> // false 345 | 346 | type Result3 = number.Compare<1, 0> // true 347 | ``` 348 | 349 | ## IntMinusSingleAbs 数字类型相减 350 | 351 | 两个数字类型相减,得到差的绝对值 352 | 353 | ::: warning 注意 354 | 该数字类型相减工具类型有较为明显的边界限制 355 | ::: 356 | 357 | **泛型参数** 358 | 359 | + N1 360 | - 约束 `number` 361 | - 必须 `是` 362 | - 注:必须是大于等于0的整数,且不超过999 363 | 364 | + N2 365 | - 约束 `number` 366 | - 必须 `是` 367 | - 注:必须是大于等于0的整数,且不超过999 368 | 369 | **示例** 370 | 371 | ```ts 372 | import { number } from 'typescript-lodash' 373 | 374 | type Result1 = number.IntMinusSingleAbs<1, 1> // 0 375 | 376 | type Result2 = number.IntMinusSingleAbs<0, 1> // 1 377 | 378 | type Result3 = number.IntMinusSingleAbs<5, 1> // 4 379 | ``` 380 | 381 | ## GetHalf 获取数字类型的一半 382 | 383 | 获得一个数字类型的一半 384 | 385 | 如果该数字类型 `N` 为偶数,则会得到 `N / 2` 的结果 386 | 387 | 如果该数字类型 `N` 为奇数,则会得到 `(N + 1) / 2` 的结果 388 | 389 | ::: warning 注意 390 | 该数字类型获取一半工具类型有较为明显的边界限制 391 | ::: 392 | 393 | **泛型参数** 394 | 395 | + N 396 | - 约束 `number` 397 | - 必须 `是` 398 | - 注:为大于等于0的整数,且不超过1000 399 | 400 | **示例** 401 | 402 | ```ts 403 | import { number } from 'typescript-lodash' 404 | 405 | type Result1 = number.GetHalf<0> // 0 406 | 407 | type Result2 = number.GetHalf<1> // 1 408 | 409 | type Result3 = number.GetHalf<2> // 1 410 | 411 | type Result4 = number.GetHalf<4> // 2 412 | ``` 413 | 414 | ## ToNumber 转为数字类型 415 | 416 | 将字符串类型(整数)转为数字类型 417 | 418 | **泛型参数** 419 | 420 | + N 421 | - 约束 `string` 422 | - 必须 `是` 423 | - 注:需要为大于等于0的整数,最大可转换9999 424 | 425 | **示例** 426 | 427 | ```ts 428 | import { number } from 'typescript-lodash' 429 | 430 | type Result1 = number.ToNumber<"123"> // 123 431 | ``` 432 | 433 | ## ParseFloat 转为浮点型 434 | 435 | 将形如数字类型转为数字类型,支持浮点数 436 | 437 | **泛型参数** 438 | 439 | + N 440 | - 约束 `NumberLike` 441 | - 必须 `是` 442 | - 注:可为正负数,整数或小数,包含小数点(不包含负号),输出结果最大支持17位,输入时,小数位末尾后可补0 443 | 444 | **示例** 445 | 446 | ```ts 447 | import { number } from 'typescript-lodash' 448 | 449 | type Result1 = number.ParseFloat<"123"> // 123 450 | 451 | type Result2 = number.ParseFloat<"123.45"> // 123.45 452 | 453 | type Result3 = number.ParseFloat<"-3.14159265358979300000000000"> // -3.141592653589793 454 | 455 | type Result4 = number.ParseFloat<123.45> // 123.45 456 | 457 | type Result4 = number.ParseFloat<123.45000> // 123.45 458 | ``` 459 | 460 | ## Add 大数相加 461 | 462 | 支持大数类型(字符串)相加,不会出现精度问题,结果类型为字符串类型 463 | 464 | **约束说明** 465 | 466 | `AdvancedNumericCharacters` 即小数点左边不能以多个 0 为开始,且为字符类型 467 | 468 | ```ts 469 | type Numbers = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 470 | 471 | type AdvancedNumericCharacters = 472 | | `${0}.${number}` 473 | | `${Exclude}${number | ""}.${number}` 474 | | `${Exclude}${Numbers | ""}.${number}` 475 | | `${Exclude}${number}` 476 | | `${Numbers}` 477 | ``` 478 | 479 | **泛型参数** 480 | 481 | + S1 482 | - 约束 `AdvancedNumericCharacters` 483 | - 必须 `是` 484 | 485 | + S2 486 | - 约束 `AdvancedNumericCharacters` 487 | - 必须 `是` 488 | 489 | **示例** 490 | 491 | ```ts 492 | import { number } from 'typescript-lodash' 493 | 494 | type Result1 = number.Add<"1", "1"> // 2 495 | 496 | type Result1 = number.Add<"9007199254740991", "9007199254740991"> // "18014398509481982.0" 497 | 498 | type Result2 = number.Add<"9007199254740991.12345", "9007199254740991.234567"> // "18014398509481982.357017" 499 | ``` 500 | 501 | -------------------------------------------------------------------------------- /documents/document/3.array.md: -------------------------------------------------------------------------------- 1 | # array 工具类型 2 | 3 | [在 CodeSandBox 中尝试](https://codesandbox.io/s/typescript-lodash-example-1l5hn?file=/src/array.ts) 4 | 5 | ## GetTuple 创建元组 6 | 7 | 创建指定长度的元组 8 | 9 | **泛型参数** 10 | 11 | + Length 12 | - 约束 `number` 13 | - 必须 `否` 14 | - 默认 `0` 15 | 16 | **示例** 17 | 18 | ```ts 19 | import { array } from "typescript-lodash" 20 | 21 | type Result1 = array.GetTuple<5> // [CanStringified, unknown, unknown, unknown, unknown] 22 | ``` 23 | 24 | ## ArraySet 修改值 25 | 26 | 将元组类型中给定索引的类型修改为新类型 27 | 28 | **泛型参数** 29 | 30 | + T 31 | - 约束 `unknown[]` 32 | - 必须 `是` 33 | 34 | + Index 35 | - 约束 `number` 36 | - 必须 `是` 37 | - 注:给定需要修改类型的索引 38 | 39 | + Value 40 | - 约束 `any` 41 | - 必须 `是` 42 | - 注:新的类型 43 | 44 | **示例** 45 | 46 | ```ts 47 | import { array } from "typescript-lodash" 48 | 49 | type Result1 = array.ArraySet<[0, 1], 0, 1> // [1, 1] 50 | ``` 51 | 52 | ## TupleToUnion 元组转联合类型 53 | 54 | 从元组类型构造联合类型 55 | 56 | **泛型参数** 57 | 58 | + T 59 | - 约束 `unknown[]` 60 | - 必须 `是` 61 | 62 | **示例** 63 | 64 | ```ts 65 | import { array } from "typescript-lodash" 66 | 67 | type Result1 = array.TupleToUnion<[0, 1]> // 0 | 1 68 | ``` 69 | 70 | ## Pop 去除最后一位 71 | 72 | 去除元组类型中最后一个类型 73 | 74 | **泛型参数** 75 | 76 | + T 77 | - 约束 `unknown[]` 78 | - 必须 `是` 79 | 80 | **示例** 81 | 82 | ```ts 83 | import { array } from "typescript-lodash" 84 | 85 | type Result1 = array.Pop<[0, 1]> // [0] 86 | ``` 87 | 88 | ## Shift 去除第一位 89 | 90 | 去除元组类型中第一个类型 91 | 92 | **泛型参数** 93 | 94 | + T 95 | - 约束 `unknown[]` 96 | - 必须 `是` 97 | 98 | **示例** 99 | 100 | ```ts 101 | import { array } from "typescript-lodash" 102 | 103 | type Result1 = array.Shift<[0, 1]> // [1] 104 | ``` 105 | 106 | ## UnShift 在前面插入 107 | 108 | 在元组类型前面插入一个类型 109 | 110 | **泛型参数** 111 | 112 | + T 113 | - 约束 `unknown[]` 114 | - 必须 `是` 115 | 116 | + Item 117 | - 约束 `any` 118 | - 必须 `是` 119 | 120 | **示例** 121 | 122 | ```ts 123 | import { array } from "typescript-lodash" 124 | 125 | type Result1 = array.UnShift<[0, 1], -1> // [-1, 0, 1] 126 | ``` 127 | 128 | ## Push 在后面插入 129 | 130 | 在元组类型后面插入一个类型 131 | 132 | **泛型参数** 133 | 134 | + T 135 | - 约束 `unknown[]` 136 | - 必须 `是` 137 | 138 | + Item 139 | - 约束 `any` 140 | - 必须 `是` 141 | 142 | **示例** 143 | 144 | ```ts 145 | import { array } from "typescript-lodash" 146 | 147 | type Result1 = array.Push<[0, 1], 2> // [0, 1, 2] 148 | ``` 149 | 150 | ## Concat 拼接元组 151 | 152 | 合并两个元组类型 153 | 154 | **泛型参数** 155 | 156 | + T 157 | - 约束 `unknown[]` 158 | - 必须 `是` 159 | 160 | + R 161 | - 约束 `unknown[]` 162 | - 必须 `是` 163 | 164 | **示例** 165 | 166 | ```ts 167 | import { array } from "typescript-lodash" 168 | 169 | type Result1 = array.Concat<[0, 1], [2]> // [0, 1, 2] 170 | ``` 171 | 172 | ## Join 元组转字符串 173 | 174 | 将元组类型转化为字符串类型 175 | 176 | **约束说明** 177 | 178 | `CanStringified` 见 [string 工具类型 - CanStringified 约束](/document/2.string.html#canstringified-可转字符的类型) 179 | 180 | **泛型参数** 181 | 182 | + T 183 | - 约束 `CanStringified[]` 184 | - 必须 `是` 185 | 186 | + SplitStr 187 | - 约束 `CanStringified` 188 | - 必须 `否` 189 | - 默认 `""` 190 | - 注:分隔每个类型的子串 191 | 192 | **示例** 193 | 194 | ```ts 195 | import { array } from "typescript-lodash" 196 | 197 | type Result1 = array.Join<[0, 1], ","> // "0,1" 198 | ``` 199 | 200 | ## Every 校验每一个都符合 201 | 202 | 元组类型中,每个类型是否都符合校验 203 | 204 | 如果是,则得到类型 `true`,否则得到类型 `false` 205 | 206 | 元组类型的长度为 0 时,会直接得到类型 `false` 207 | 208 | **泛型参数** 209 | 210 | + T 211 | - 约束 `unknown[]` 212 | - 必须 `是` 213 | 214 | + Check 215 | - 约束 `any` 216 | - 必须 `是` 217 | - 默认 `""` 218 | - 注:用于校验元组中的类型是否符合其的约束 219 | 220 | **示例** 221 | 222 | ```ts 223 | import { array } from "typescript-lodash" 224 | 225 | type Result1 = array.Every<[0, 1], number> // true 226 | 227 | type Result2 = array.Every<[], number> // false 228 | 229 | type Result3 = array.Every<[1, "2"], number> // false 230 | ``` 231 | 232 | ## Some 校验有一个符合 233 | 234 | 元组类型中,是否存在符合校验的类型 235 | 236 | 如果是,则得到类型 `true`,否则得到类型 `false` 237 | 238 | **泛型参数** 239 | 240 | + T 241 | - 约束 `unknown[]` 242 | - 必须 `是` 243 | 244 | + Check 245 | - 约束 `any` 246 | - 必须 `否` 247 | - 默认 `""` 248 | - 注:用于校验元组中是否存在符合其约束的类型 249 | 250 | **示例** 251 | 252 | ```ts 253 | import { array } from "typescript-lodash" 254 | 255 | type Result1 = array.Some<[0, 1], number> // true 256 | 257 | type Result2 = array.Some<[], number> // false 258 | 259 | type Result3 = array.Some<[1, "2"], number> // true 260 | ``` 261 | 262 | ## Fill 填充元组 263 | 264 | 以一个类型填充元组 265 | 266 | **泛型参数** 267 | 268 | + T 269 | - 约束 `unknown[]` 270 | - 必须 `是` 271 | 272 | + F 273 | - 约束 `any` 274 | - 必须 `否` 275 | - 默认 `undefined` 276 | - 注:用于填充的类型 277 | 278 | **示例** 279 | 280 | ```ts 281 | import { array } from "typescript-lodash" 282 | 283 | type Result1 = array.Fill<[0, 1], 0> // [0, 1] 284 | ``` 285 | 286 | ## Filter 过滤 287 | 288 | 在元组中过滤出符合给定约束的类型并返回新元组 289 | 290 | **泛型参数** 291 | 292 | + T 293 | - 约束 `unknown[]` 294 | - 必须 `是` 295 | 296 | + C 297 | - 约束 `any` 298 | - 必须 `是` 299 | - 注:用于填充的类型 300 | 301 | + Strict 302 | - 约束 `boolean` 303 | - 必须 `否` 304 | - 默认 `false` 305 | - 注:严格模式,在该模式下,类型必须一模一样才能通过校验,如类型 `any` 不能分配给类型 `1` 306 | 307 | **示例** 308 | 309 | ```ts 310 | import { array } from "typescript-lodash" 311 | 312 | type Result1 = array.Filter<[0, 1], 0> // [0] 313 | 314 | type Result2 = array.Filter<[0, 1, 2, 3, "4"], string> // ["4"] 315 | 316 | type Result3 = array.Filter<[any, 1, 2], any, true> // [any] 317 | ``` 318 | 319 | ## MapWidthIndex 带索引映射 320 | 321 | 将元组类型中每个类型映射为携带索引的对象类型 322 | 323 | **泛型参数** 324 | 325 | + T 326 | - 约束 `unknown[]` 327 | - 必须 `是` 328 | 329 | **结果类型** 330 | 331 | ```ts 332 | interface IndexMappedItem { 333 | item: Item 334 | index: Index 335 | tuple: Tuple 336 | } 337 | ``` 338 | 339 | **示例** 340 | 341 | ```ts 342 | import { array } from "typescript-lodash" 343 | 344 | type Result1 = array.MapWidthIndex<[1, 2]> // [{ item: 1; index: 0;tuple: [1, 2]; }, { item: 2; index: 1;tuple: [1, 2]; }] 345 | ``` 346 | 347 | ## Reverse 反转元组 348 | 349 | 将元组反转 350 | 351 | **泛型参数** 352 | 353 | + T 354 | - 约束 `unknown[]` 355 | - 必须 `是` 356 | 357 | **示例** 358 | 359 | ```ts 360 | import { array } from "typescript-lodash" 361 | 362 | type Result1 = array.Reverse<[]> // [] 363 | 364 | type Result2 = array.Reverse<[1, 2]> // [2, 1] 365 | ``` 366 | 367 | ## Find 在元组中查找第一个 368 | 369 | 在元组中从左至右查找第一个符合给定类型约束的类型,如没有,则得到 `null` 370 | 371 | **泛型参数** 372 | 373 | + T 374 | - 约束 `unknown[]` 375 | - 必须 `是` 376 | 377 | + C 378 | - 约束 `any` 379 | - 必须 `是` 380 | 381 | **示例** 382 | 383 | ```ts 384 | import { array } from "typescript-lodash" 385 | 386 | type Result1 = array.Find<[1, 2], 1> // 1 387 | 388 | type Result2 = array.Find<[1, 2], 3> // null 389 | ``` 390 | 391 | ## FindLast 在元组中查找最后一个 392 | 393 | 在元组中从左至右查找最后一个符合给定类型约束的类型,如没有,则得到 `null` 394 | 395 | **泛型参数** 396 | 397 | + T 398 | - 约束 `unknown[]` 399 | - 必须 `是` 400 | 401 | + C 402 | - 约束 `any` 403 | - 必须 `是` 404 | 405 | **示例** 406 | 407 | ```ts 408 | import { array } from "typescript-lodash" 409 | 410 | type Result1 = array.FindLast<[1, 2], 1> // 1 411 | 412 | type Result2 = array.FindLast<[1, 2], 3> // null 413 | ``` 414 | 415 | ## FindIndex 在元组中查找第一个获取索引 416 | 417 | 在元组中从左至右查找第一个符合给定类型约束的类型,如果有,得到其索引,如没有,则得到 `-1` 418 | 419 | **泛型参数** 420 | 421 | + T 422 | - 约束 `unknown[]` 423 | - 必须 `是` 424 | 425 | + C 426 | - 约束 `any` 427 | - 必须 `是` 428 | 429 | + Strict 430 | - 约束 `boolean` 431 | - 必须 `否` 432 | - 默认 `false` 433 | - 注:同 `array.Filter` 434 | 435 | **示例** 436 | 437 | ```ts 438 | import { array } from "typescript-lodash" 439 | 440 | type Result1 = array.FindIndex<[1, 2], 1> // 0 441 | 442 | type Result2 = array.FindIndex<[1, 2], 3> // -1 443 | ``` 444 | 445 | ## FindLastIndex 在元组中查找最后一个获取索引 446 | 447 | 在元组中从左至右查找最后一个符合给定类型约束的类型,如果有,得到其索引,如没有,则得到 `-1` 448 | 449 | **泛型参数** 450 | 451 | + T 452 | - 约束 `unknown[]` 453 | - 必须 `是` 454 | 455 | + C 456 | - 约束 `any` 457 | - 必须 `是` 458 | 459 | + Strict 460 | - 约束 `boolean` 461 | - 必须 `否` 462 | - 默认 `false` 463 | - 注:同 `array.Filter` 464 | 465 | **示例** 466 | 467 | ```ts 468 | import { array } from "typescript-lodash" 469 | 470 | type Result1 = array.FindLastIndex<[1, 2], 1> // 0 471 | 472 | type Result2 = array.FindLastIndex<[1, 2], 3> // -1 473 | ``` 474 | 475 | ## Flat 扁平化 476 | 477 | 将元组扁平化 478 | 479 | **泛型参数** 480 | 481 | + T 482 | - 约束 `unknown[]` 483 | - 必须 `是` 484 | 485 | **示例** 486 | 487 | ```ts 488 | import { array } from "typescript-lodash" 489 | 490 | type Result1 = array.Flat<[1, [2]]> // [1, 2] 491 | 492 | type Result2 = array.Flat<[1, [2, [3]]]> // [1, 2, [3]] 493 | ``` 494 | 495 | ## Includes 是否存在 496 | 497 | 在元组中查找符合给定类型约束的类型 498 | 499 | 如果有,则得到 `true`,否则得到 `false` 500 | 501 | **泛型参数** 502 | 503 | + T 504 | - 约束 `unknown[]` 505 | - 必须 `是` 506 | 507 | + C 508 | - 约束 `any` 509 | - 必须 `是` 510 | 511 | **示例** 512 | 513 | ```ts 514 | import { array } from "typescript-lodash" 515 | 516 | type Result1 = array.Includes<[1, "2", 3], string> // true 517 | 518 | type Result2 = array.Includes<[1], string> // false 519 | ``` 520 | 521 | ## Slice 截取元组 522 | 523 | 从给定的元组类型中,按照给定的起始索引和结束索引截取元组 524 | 525 | **泛型参数** 526 | 527 | + T 528 | - 约束 `unknown[]` 529 | - 必须 `是` 530 | 531 | + Start 532 | - 约束 `number` 533 | - 必须 `是` 534 | - 注:指定的起始索引,需为大于等于 0 的整数 535 | 536 | + End 537 | - 约束 `number` 538 | - 必须 `是` 539 | - 注:指定的结束索引,需为大于等于 0 的整数 540 | 541 | **示例** 542 | 543 | ```ts 544 | import { array } from "typescript-lodash" 545 | 546 | type Result1 = array.Slice<[1, 2, 3], 0, 1> // [1] 547 | 548 | type Result2 = array.Slice<[1, 2, 3], 0, 0> // [] 549 | 550 | type Result3 = array.Slice<[1, 2, 3], 1, 0> // [] 551 | 552 | type Result4 = array.Slice<[1, 2, 3], 1, 6> // [1, 2, 3] 553 | ``` 554 | 555 | ## Sort 排序 556 | 557 | 对给定的元组按从小到大进行排序 558 | 559 | ::: danger 注意 560 | 该元组类型排序工具类型有明显的边界限制,最多仅支持长度为2的元组的排序 561 | ::: 562 | 563 | **泛型参数** 564 | 565 | + T 566 | - 约束 `number[]` 567 | - 必须 `是` 568 | - 注:元组中每一项都必须为非负整数类型 569 | 570 | **示例** 571 | 572 | ```ts 573 | import { array } from "typescript-lodash" 574 | 575 | type Result = array.Sort<[2, 1]> // [1, 2] 576 | ``` 577 | 578 | ## SortMany 排序 579 | 580 | 对给定的元组按从小到大进行排序,比 `array.Sort` 支持更多项 581 | 582 | [见此PullRequest](https://github.com/kawayiLinLin/typescript-lodash/pull/4) 583 | 584 | 585 | **泛型参数** 586 | 587 | + T 588 | - 约束 `number[]` 589 | - 必须 `是` 590 | - 注:元组中每一项都必须为非负整数类型 591 | 592 | **示例** 593 | 594 | ```ts 595 | import { array } from "typescript-lodash" 596 | 597 | type Result = array.SortMany<[2, 1, 3, 50, 1]> // [1, 1, 2, 3, 50] 598 | ``` -------------------------------------------------------------------------------- /lib/array.ts: -------------------------------------------------------------------------------- 1 | import { common, array, number, string } from ".." 2 | 3 | /** 4 | * 构造长度一定(Length)的元组 5 | */ 6 | type GetTuple = GetTupleHelper 7 | 8 | type GetTupleHelper< 9 | Length extends number = 0, 10 | R extends unknown[] = [] 11 | > = R["length"] extends Length ? R : GetTupleHelper 12 | 13 | type SetHelper< 14 | T extends unknown[], 15 | Index extends number, 16 | Value, 17 | Offset extends number = 0, 18 | Cache extends unknown[] = [] 19 | > = Offset extends T["length"] 20 | ? Cache 21 | : SetHelper< 22 | T, 23 | Index, 24 | Value, 25 | number.IntAddSimple, 26 | Push 27 | > 28 | 29 | type ArraySet = SetHelper< 30 | T, 31 | Index, 32 | Value 33 | > 34 | 35 | /** 36 | * 从元(数)组类型构造联合类型 37 | */ 38 | type TupleToUnion = T[number] 39 | 40 | /** 41 | * 去掉数组的最后一位 42 | * @see https://juejin.cn/post/7045536402112512007#heading-2 43 | */ 44 | type Pop = T extends [...infer LeftRest, infer Last] 45 | ? LeftRest 46 | : never 47 | 48 | /** 49 | * 去掉数组的第一位 50 | */ 51 | type Shift = T extends [infer First, ...infer RightRest] 52 | ? RightRest 53 | : never 54 | 55 | /** 56 | * 在数组前面插入一位 57 | */ 58 | type UnShift = [Item, ...T] 59 | 60 | /** 61 | * 在数组最后插入一位 62 | */ 63 | type Push = [...T, Item] 64 | /** */ 65 | type Concat = [...T, ...R] 66 | /** */ 67 | type Join< 68 | T extends string.CanStringified[], 69 | SplitStr extends string.CanStringified = "" 70 | > = T["length"] extends 0 71 | ? "" 72 | : T extends [infer Left, ...infer RightRest] 73 | ? Left extends string.CanStringified 74 | ? RightRest extends string.CanStringified[] 75 | ? `${Left}${T["length"] extends 1 ? "" : SplitStr}${Join< 76 | RightRest, 77 | SplitStr 78 | >}` 79 | : never 80 | : never 81 | : never 82 | 83 | type EveryHelper< 84 | T extends unknown[], 85 | Check, 86 | Offset extends number = 0, 87 | CacheBool extends boolean = true 88 | > = common.Or< 89 | number.IsEqual, 90 | common.Not 91 | > extends true 92 | ? CacheBool 93 | : EveryHelper< 94 | T, 95 | Check, 96 | number.IntAddSimple, 97 | common.CheckLeftIsExtendsRight 98 | > 99 | /** */ 100 | type Every = T["length"] extends 0 101 | ? false 102 | : EveryHelper 103 | 104 | type SomeHelper< 105 | T extends unknown[], 106 | Check, 107 | Offset extends number = 0, 108 | CacheBool extends boolean = false 109 | > = common.Or< 110 | number.IsEqual, 111 | CacheBool 112 | > extends true 113 | ? CacheBool 114 | : SomeHelper< 115 | T, 116 | Check, 117 | number.IntAddSimple, 118 | common.CheckLeftIsExtendsRight 119 | > 120 | /** */ 121 | type Some = SomeHelper 122 | 123 | type FillHelper< 124 | T extends unknown[], 125 | F, 126 | Offset extends number = 0 127 | > = T["length"] extends 0 128 | ? F[] 129 | : Offset extends T["length"] 130 | ? common.IsEqual extends true /** any[] -> T[] */ 131 | ? T 132 | : F[] 133 | : FillHelper, F>, F, number.IntAddSimple> 134 | /** */ 135 | type Fill = FillHelper 136 | 137 | type FilterHelper< 138 | T extends unknown[], 139 | C, 140 | Strict extends boolean, 141 | Offset extends number = 0, 142 | Cache extends unknown[] = [] 143 | > = Offset extends T["length"] 144 | ? Cache 145 | : FilterHelper< 146 | T, 147 | C, 148 | Strict, 149 | number.IntAddSimple, 150 | common.And> extends true 151 | ? array.Push 152 | : common.And< 153 | common.Not, 154 | common.CheckLeftIsExtendsRight 155 | > extends true 156 | ? array.Push 157 | : Cache 158 | > 159 | /** */ 160 | type Filter< 161 | T extends unknown[], 162 | C, 163 | Strict extends boolean = false 164 | > = FilterHelper 165 | 166 | type FindHelper< 167 | T extends unknown[], 168 | C, 169 | Offset extends number = 0 170 | > = Offset extends T["length"] 171 | ? null 172 | : common.CheckLeftIsExtendsRight extends true 173 | ? T[Offset] 174 | : FindHelper> 175 | /** */ 176 | type Find = FindHelper 177 | 178 | type FindIndexHelper< 179 | T extends unknown[], 180 | C, 181 | Strict extends boolean = false, 182 | Offset extends number = 0 183 | > = Offset extends T["length"] 184 | ? -1 185 | : common.And, Strict> extends true 186 | ? Offset 187 | : common.And< 188 | common.CheckLeftIsExtendsRight, 189 | common.Not 190 | > extends true 191 | ? Offset 192 | : FindIndexHelper> 193 | /** */ 194 | type FindIndex< 195 | T extends unknown[], 196 | C, 197 | Strict extends boolean = false 198 | > = FindIndexHelper 199 | 200 | type ReverseHelper< 201 | T extends unknown[], 202 | Offset extends number = 0, 203 | Cache extends unknown[] = [] 204 | > = Cache["length"] extends T["length"] 205 | ? Cache 206 | : ReverseHelper, UnShift> 207 | /** */ 208 | type Reverse = ReverseHelper 209 | /** */ 210 | type FindLast = Find, C> 211 | 212 | interface IndexMappedItem { 213 | item: Item 214 | index: Index 215 | tuple: Tuple 216 | } 217 | 218 | type MapWidthIndexHelper< 219 | T extends unknown[], 220 | Offset extends number = 0, 221 | Cache extends unknown[] = [] 222 | > = T["length"] extends Offset 223 | ? Cache 224 | : MapWidthIndexHelper< 225 | T, 226 | number.IntAddSimple, 227 | Push> 228 | > 229 | 230 | type MapWidthIndex = MapWidthIndexHelper 231 | 232 | type FindLastIndexHelper< 233 | T extends unknown[], 234 | C, 235 | Item = Find>, IndexMappedItem> 236 | > = Item extends IndexMappedItem ? Item["index"] : -1 237 | 238 | type FindLastIndex = FindLastIndexHelper 239 | 240 | type FlatHelper< 241 | T extends unknown[], 242 | Offset extends number = 0, 243 | Cache extends unknown[] = [] 244 | > = Offset extends T["length"] 245 | ? Cache 246 | : FlatHelper< 247 | T, 248 | number.IntAddSimple, 249 | T[Offset] extends unknown[] 250 | ? Concat 251 | : Push 252 | > 253 | 254 | type Flat = FlatHelper 255 | 256 | type Includes = common.CheckLeftIsExtendsRight< 257 | C, 258 | TupleToUnion 259 | > 260 | 261 | type SliceHelper< 262 | T extends unknown[], 263 | Start extends number, 264 | End extends number, 265 | Offset extends number = 0, 266 | Cache extends unknown[] = [] 267 | > = number.IsEqual extends true 268 | ? Cache 269 | : SliceHelper< 270 | T, 271 | Start, 272 | End, 273 | number.IntAddSimple, 274 | common.And3< 275 | common.Or, number.IsEqual>, 276 | common.Or, number.IsEqual>, 277 | common.Or< 278 | number.Compare, 279 | number.IsEqual 280 | > 281 | > extends true 282 | ? array.Push 283 | : Cache 284 | > 285 | 286 | type Slice< 287 | T extends unknown[], 288 | Start extends number, 289 | End extends number 290 | > = SliceHelper 291 | 292 | type SortHepler2< 293 | T extends number[], 294 | Offset extends number = 0, 295 | Offset1 extends number = 0, 296 | Offset1Added extends number = number.IntAddSimple, 297 | Seted1 extends unknown[] = ArraySet, 298 | Seted2 extends unknown[] = ArraySet 299 | > = number.IntAddSimple< 300 | number.IntAddSimple, 301 | 1 302 | > extends T["length"] 303 | ? SortHepler1> 304 | : SortHepler2< 305 | number.Compare extends true 306 | ? Seted2 extends number[] 307 | ? Seted2 308 | : never 309 | : T, 310 | number.IntAddSimple 311 | > 312 | 313 | type SortHepler1< 314 | T extends number[], 315 | Offset extends number = 0 316 | > = Offset extends T["length"] ? T : SortHepler2 317 | 318 | type Sort = SortHepler1 319 | 320 | type Sort1Helper1< 321 | T extends any[], 322 | Offset extends number = 0 323 | > = Offset extends T["length"] ? T : Sort1Helper1, number.IntAddSimple> 324 | 325 | type Sort1Helper2 = T extends [infer X, infer Y, ...infer Rest] 326 | ? number.Compare extends true 327 | ? [Y, ...Sort1Helper1<[X, ...Rest]>] 328 | : [X, ...Sort1Helper1<[Y, ...Rest]>] 329 | : T 330 | 331 | /** 332 | * 冒泡排序 333 | * 使用递归的方式,比 array.Sort 支持更多项的排序 334 | * @see https://github.com/kawayiLinLin/typescript-lodash/pull/4 335 | */ 336 | type SortMany = Sort1Helper1 337 | 338 | 339 | type TupleKeysHelper< 340 | T extends unknown[], 341 | Offset extends number = 0 342 | > = Offset extends T["length"] 343 | ? T 344 | : TupleKeysHelper, number.IntAddSimple> 345 | 346 | type TupleKeys = TupleKeysHelper 347 | 348 | /** 349 | * @exports 350 | */ 351 | type IndexOf< 352 | T extends unknown[], 353 | C, 354 | Strict extends boolean = false 355 | > = FindIndex 356 | 357 | type LastIndexOf = FindLastIndex 358 | 359 | 360 | export type { 361 | GetTuple, 362 | TupleToUnion, 363 | ArraySet, 364 | Pop, 365 | Shift, 366 | UnShift, 367 | Push, 368 | Concat, 369 | Join, 370 | Every, 371 | Some, 372 | Fill, 373 | Filter, 374 | Find, 375 | FindIndex, 376 | Reverse, 377 | MapWidthIndex, 378 | FindLast, 379 | FindLastIndex, 380 | Flat, 381 | Includes, 382 | Slice, 383 | Sort, 384 | SortMany, 385 | TupleKeys, 386 | IndexOf, 387 | LastIndexOf, 388 | } 389 | -------------------------------------------------------------------------------- /documents/document/2.string.md: -------------------------------------------------------------------------------- 1 | # string 工具类型 2 | 3 | [在 CodeSandBox 中尝试](https://codesandbox.io/s/typescript-lodash-example-1l5hn?file=/src/string.ts) 4 | 5 | ## CanStringified 可转字符的类型 6 | 7 | 可以转字符类型的类型,如 `0`、`"haha"`、`true`、`null`、`undefined` 8 | 9 | **用于约束其他类型** 10 | 11 | ```ts 12 | type CanStringified = string | number | bigint | boolean | null | undefined 13 | ``` 14 | 15 | ## Stringify 转字符串 16 | 17 | 将符合约束的类型转为字符串类型 18 | 19 | **泛型参数** 20 | 21 | + T 22 | - 约束 `CanStringified` 23 | - 必须 `是` 24 | 25 | **示例** 26 | 27 | ```ts 28 | import { string } from "typescript-lodash" 29 | 30 | type Result1 = string.Stringify<1> // "1" 31 | 32 | type Result2 = string.Stringify<"haha"> // "haha" 33 | 34 | type Result3 = string.Stringify // "true" 35 | 36 | type Result4 = string.Stringify // "null" 37 | 38 | type Result5 = string.Stringify // "undefined" 39 | 40 | type Result6 = string.Stringify<1n> // "1" 41 | ``` 42 | 43 | ## GetChars 获取字符 44 | 45 | 获取字符串类型中所有字符构成的联合类型 46 | 47 | **泛型参数** 48 | 49 | + S 50 | - 约束 `string` 51 | - 必须 `是` 52 | 53 | **示例** 54 | 55 | ```ts 56 | import { string } from "typescript-lodash" 57 | 58 | type Result1 = string.GetChars<'abc'> // 'a' | 'b' | 'c' 59 | 60 | type Result2 = string.GetChars<""> // never 61 | ``` 62 | 63 | ## Split 分割字符串 64 | 65 | 将字符串类型按照子串分割成元组类型 66 | 67 | **泛型参数** 68 | 69 | + S 70 | - 约束 `string` 71 | - 必须 `是` 72 | 73 | + SplitStr 74 | - 约束 `string` 75 | - 必须 `否` 76 | - 默认 `""` 77 | - 注:按照 SplitStr 分割字符串类型 78 | 79 | **示例** 80 | 81 | ```ts 82 | import { string } from "typescript-lodash" 83 | 84 | type Result1 = string.Split<'abc'> // ['a', 'b', 'c'] 85 | 86 | type Result2 = string.Split<'1,2,3', ','> // ["1", "2", "3"] 87 | 88 | type Result3 = string.Split<"", ','> // [] 89 | ``` 90 | 91 | ## GetStringLength 获取字符串长度 92 | 93 | 获取字符串类型的长度 94 | 95 | **泛型参数** 96 | 97 | + S 98 | - 约束 `string` 99 | - 必须 `是` 100 | 101 | **示例** 102 | 103 | ```ts 104 | import { string } from "typescript-lodash" 105 | 106 | type Result1 = string.GetStringLength<"123"> // 3 107 | 108 | type Result2 = string.GetStringLength<""> // 0 109 | ``` 110 | 111 | ## CharAt 获取字符 112 | 113 | 获取字符串类型中给定索引位的字符 114 | 115 | **泛型参数** 116 | 117 | + S 118 | - 约束 `string` 119 | - 必须 `是` 120 | 121 | + I 122 | - 约束 `number` 123 | - 必须 `是` 124 | - 注:给定的索引位需要大于等于0 125 | 126 | **示例** 127 | 128 | ```ts 129 | import { string } from "typescript-lodash" 130 | 131 | type Result1 = string.CharAt<"123", 0> // "1" 132 | 133 | type Result2 = string.CharAt<"123", 2> // "3" 134 | 135 | type Result3 = string.CharAt<"123", 3> // undefined 136 | ``` 137 | 138 | ## Concat 拼接字符 139 | 140 | 拼接两个字符串类型成为一个新的字符串类型 141 | 142 | **泛型参数** 143 | 144 | + S1 145 | - 约束 `string` 146 | - 必须 `是` 147 | 148 | + S2 149 | - 约束 `string` 150 | - 必须 `是` 151 | 152 | **示例** 153 | 154 | ```ts 155 | import { string } from "typescript-lodash" 156 | 157 | type Result1 = string.Concat<"123", "456"> // "123456" 158 | ``` 159 | 160 | ## Includes 判断包含子串 161 | 162 | 判断字符串类型中是否包含子串 163 | 164 | 如果是,则得到 `true`、否则得到 `false` 165 | 166 | **泛型参数** 167 | 168 | + S1 169 | - 约束 `string` 170 | - 必须 `是` 171 | 172 | + S2 173 | - 约束 `string` 174 | - 必须 `是` 175 | - 注:需要判断是否包含的子串 176 | 177 | **示例** 178 | 179 | ```ts 180 | import { string } from "typescript-lodash" 181 | 182 | type Result1 = string.Include<"123", "12"> // true 183 | 184 | type Result2 = string.Include<"123", "34"> // false 185 | ``` 186 | 187 | ## StartsWith 判断由子串开始 188 | 189 | 判断字符串类型是否由给定的子串开始 190 | 191 | 如果是,则得到 `true`、否则得到 `false` 192 | 193 | **泛型参数** 194 | 195 | + S1 196 | - 约束 `string` 197 | - 必须 `是` 198 | 199 | + S2 200 | - 约束 `string` 201 | - 必须 `是` 202 | - 注:需要判断是否由其开始的子串 203 | 204 | **示例** 205 | 206 | ```ts 207 | import { string } from "typescript-lodash" 208 | 209 | type Result1 = string.StartsWith<"123", "12"> // true 210 | 211 | type Result2 = string.StartsWith<"123", "23"> // false 212 | ``` 213 | 214 | ## EndsWith 判断由子串结束 215 | 216 | 判断字符串类型是否由给定的子串结束 217 | 218 | 如果是,则得到 `true`、否则得到 `false` 219 | 220 | **泛型参数** 221 | 222 | + S1 223 | - 约束 `string` 224 | - 必须 `是` 225 | 226 | + S2 227 | - 约束 `string` 228 | - 必须 `是` 229 | - 注:需要判断是否由其结束的子串 230 | 231 | **示例** 232 | 233 | ```ts 234 | import { string } from "typescript-lodash" 235 | 236 | type Result1 = string.EndsWith<"123", "12"> // false 237 | 238 | type Result2 = string.EndsWith<"123", "23"> // true 239 | ``` 240 | 241 | ## IndexOf 查询子串第一个起始索引 242 | 243 | 从左往右查询字符串类型中给定的子串出现的第一个位置的起始索引,如果没有,则得到 -1 244 | 245 | **泛型参数** 246 | 247 | + S1 248 | - 约束 `string` 249 | - 必须 `是` 250 | 251 | + S2 252 | - 约束 `string` 253 | - 必须 `是` 254 | - 注:需要获得出现位置的子串 255 | 256 | **示例** 257 | 258 | ```ts 259 | import { string } from "typescript-lodash" 260 | 261 | type Result1 = string.IndexOf<"123", "1"> // 0 262 | 263 | type Result2 = string.IndexOf<"123", "4"> // -1 264 | ``` 265 | 266 | ## LastIndexOf 查询子串最后一个起始索引 267 | 268 | 从左往右查询字符串类型中给定的子串出现的最后一个位置的起始索引,如果没有,则得到 -1 269 | 270 | **泛型参数** 271 | 272 | + S1 273 | - 约束 `string` 274 | - 必须 `是` 275 | 276 | + S2 277 | - 约束 `string` 278 | - 必须 `是` 279 | - 注:需要获得出现位置的子串 280 | 281 | **示例** 282 | 283 | ```ts 284 | import { string } from "typescript-lodash" 285 | 286 | type Result1 = string.LastIndexOf<"123", "3"> // 2 287 | 288 | type Result2 = string.LastIndexOf<"123", "4"> // -1 289 | ``` 290 | 291 | ## Replace 查找并替换一处子串 292 | 293 | 在字符串类型中匹配第一个子串并替换成新字符串类型 294 | 295 | **泛型参数** 296 | 297 | + S1 298 | - 约束 `string` 299 | - 必须 `是` 300 | 301 | + MatchStr 302 | - 约束 `string` 303 | - 必须 `是` 304 | - 注:需要被替换的子串 305 | 306 | + ReplaceStr 307 | - 约束 `string` 308 | - 必须 `是` 309 | - 注:需要替换的子串 310 | 311 | **示例** 312 | 313 | ```ts 314 | import { string } from "typescript-lodash" 315 | 316 | type Result1 = string.Replace<"123", "3", "4"> // "124" 317 | 318 | type Result2 = string.Replace<"123", "4", "5"> // "123" 319 | ``` 320 | 321 | ## ReplaceAll 查找并替换所有子串 322 | 323 | 在字符串类型中匹配所有子串并替换成新字符串类型 324 | 325 | **泛型参数** 326 | 327 | + S1 328 | - 约束 `string` 329 | - 必须 `是` 330 | 331 | + MatchStr 332 | - 约束 `string` 333 | - 必须 `是` 334 | - 注:需要被替换的子串 335 | 336 | + ReplaceStr 337 | - 约束 `string` 338 | - 必须 `是` 339 | - 注:需要替换的子串 340 | 341 | **示例** 342 | 343 | ```ts 344 | import { string } from "typescript-lodash" 345 | 346 | type Result1 = string.ReplaceAll<"333", "4"> // "444" 347 | 348 | type Result2 = string.ReplaceAll<"123", "4"> // "123" 349 | ``` 350 | 351 | ## Repeat 重复字符串 352 | 353 | 重复指定次数的字符串类型,并生成新字符串 354 | 355 | **泛型参数** 356 | 357 | + S 358 | - 约束 `string` 359 | - 必须 `是` 360 | 361 | + Times 362 | - 约束 `number` 363 | - 必须 `否` 364 | - 默认 `1` 365 | - 注:给定需要重复的次数,需为大于等于 0 的整数 366 | 367 | **示例** 368 | 369 | ```ts 370 | import { string } from "typescript-lodash" 371 | 372 | type Result1 = string.Repeat<"123", 4> // "123123123123" 373 | 374 | type Result2 = string.Repeat<"123", 0> // "" 375 | ``` 376 | 377 | ## PadStart 在前面填充 378 | 379 | 当字符串类型长度低于给定值时,在字符串前面以给定字符串类型进行填充,直到满足给定长度 380 | 381 | **泛型参数** 382 | 383 | + S 384 | - 约束 `string` 385 | - 必须 `是` 386 | 387 | + N 388 | - 约束 `number` 389 | - 必须 `否` 390 | - 默认 `0` 391 | - 注:给定字符串需要达到的长度,需为大于等于 0 的整数 392 | 393 | + FillS 394 | - 约束 `string` 395 | - 必须 `否` 396 | - 默认 `" "` 397 | - 注:填充字符 398 | 399 | **示例** 400 | 401 | ```ts 402 | import { string } from "typescript-lodash" 403 | 404 | type Result1 = string.PadStart<"123", 4> // " 123" 405 | 406 | type Result2 = string.PadStart<"123", 5, 'x'> // "xx123" 407 | ``` 408 | 409 | ## PadEnd 在后面填充 410 | 411 | 当字符串类型长度低于给定值时,在字符串后面以给定字符串类型进行填充,直到满足给定长度 412 | 413 | **泛型参数** 414 | 415 | + S 416 | - 约束 `string` 417 | - 必须 `是` 418 | 419 | + N 420 | - 约束 `number` 421 | - 必须 `否` 422 | - 默认 `0` 423 | - 注:给定字符串需要达到的长度,需为大于等于 0 的整数 424 | 425 | + FillS 426 | - 约束 `string` 427 | - 必须 `否` 428 | - 默认 `" "` 429 | - 注:填充字符 430 | 431 | **示例** 432 | 433 | ```ts 434 | import { string } from "typescript-lodash" 435 | 436 | type Result1 = string.PadEnd<"123", 4> // "123 " 437 | 438 | type Result2 = string.PadEnd<"123", 5, 'x'> // "123xx" 439 | ``` 440 | 441 | ## TrimLeft 去掉左边空格 442 | 443 | 去掉字符串类型左侧的所有空格、制表符、换行符 444 | 445 | **泛型参数** 446 | 447 | + S 448 | - 约束 `string` 449 | - 必须 `是` 450 | 451 | **示例** 452 | 453 | ```ts 454 | import { string } from "typescript-lodash" 455 | 456 | type Result1 = string.TrimLeft<" 123 "> // "123 " 457 | ``` 458 | 459 | ## TrimRight 去掉右边空格 460 | 461 | 去掉字符串类型右侧的所有空格、制表符、换行符 462 | 463 | **泛型参数** 464 | 465 | + S 466 | - 约束 `string` 467 | - 必须 `是` 468 | 469 | **示例** 470 | 471 | ```ts 472 | import { string } from "typescript-lodash" 473 | 474 | type Result1 = string.TrimLeft<" 123 "> // " 123" 475 | ``` 476 | 477 | ## Trim 去掉两边空格 478 | 479 | 去掉字符串类型两侧的所有空格、制表符、换行符 480 | 481 | **泛型参数** 482 | 483 | + S 484 | - 约束 `string` 485 | - 必须 `是` 486 | 487 | **示例** 488 | 489 | ```ts 490 | import { string } from "typescript-lodash" 491 | 492 | type Result1 = string.TrimLeft<" 123 "> // "123" 493 | ``` 494 | 495 | ## ToUpperCase 转大写 496 | 497 | 将字符串类型中的英文字母全部转为大写 498 | 499 | **泛型参数** 500 | 501 | + S 502 | - 约束 `string` 503 | - 必须 `是` 504 | 505 | **示例** 506 | 507 | ```ts 508 | import { string } from "typescript-lodash" 509 | 510 | type Result1 = string.ToUpperCase<"abc"> // "ABC" 511 | ``` 512 | 513 | ## ToLowerCase 转小写 514 | 515 | 将字符串类型中的英文字母全部转为小写 516 | 517 | **泛型参数** 518 | 519 | + S 520 | - 约束 `string` 521 | - 必须 `是` 522 | 523 | **示例** 524 | 525 | ```ts 526 | import { string } from "typescript-lodash" 527 | 528 | type Result1 = string.ToUpperCase<"ABC"> // "abc" 529 | ``` 530 | 531 | ## SubString 截取字符串 532 | 533 | 从给定的字符串类型中,按照给定的起始索引和结束索引截取字符串 534 | 535 | **泛型参数** 536 | 537 | + S 538 | - 约束 `string` 539 | - 必须 `是` 540 | 541 | + Start 542 | - 约束 `number` 543 | - 必须 `是` 544 | - 注:指定的起始索引,需为大于等于 0 的整数 545 | 546 | + End 547 | - 约束 `number` 548 | - 必须 `是` 549 | - 注:指定的结束索引,需为大于等于 0 的整数 550 | 551 | **示例** 552 | 553 | ```ts 554 | import { string } from "typescript-lodash" 555 | 556 | type Result1 = string.SubString<"12345", 0, 1> // "1" 557 | 558 | type Result2 = string.SubString<"12345", 0, 0> // "" 559 | 560 | type Result3 = string.SubString<"12345", 1, 0> // "" 561 | ``` 562 | 563 | ## SubStr 截取一定长度的字符串 564 | 565 | 从给定的字符串类型中,按照给定的起始索引和长度截取字符串 566 | 567 | **泛型参数** 568 | 569 | + S 570 | - 约束 `string` 571 | - 必须 `是` 572 | 573 | + Start 574 | - 约束 `number` 575 | - 必须 `是` 576 | - 注:指定的起始索引,需为大于等于 0 的整数 577 | 578 | + Len 579 | - 约束 `number` 580 | - 必须 `是` 581 | - 注:指定的长度,需为大于等于 0 的整数 582 | 583 | **示例** 584 | 585 | ```ts 586 | import { string } from "typescript-lodash" 587 | 588 | type Result1 = string.SubStr<"12345", 1, 1> // "2" 589 | 590 | type Result2 = string.SubStr<"12345", 0, 0> // "" 591 | 592 | type Result3 = string.SubStr<"12345", 3, 2> // "45" 593 | ``` -------------------------------------------------------------------------------- /lib/number.ts: -------------------------------------------------------------------------------- 1 | import { number, array, string, common } from ".." 2 | 3 | type NumberLike = number | `${number}` 4 | /** 5 | * number类型是否为0 6 | */ 7 | type IsZero = common.CheckLeftIsExtendsRight 8 | 9 | /** 10 | * number类型是否大于0 11 | */ 12 | type IsOverZero = IsZero extends true 13 | ? false 14 | : common.CheckLeftIsExtendsRight< 15 | string.Stringify extends `${"-"}${infer Rest}` ? Rest : false, 16 | false 17 | > 18 | 19 | /** 20 | * number类型是否小于0 21 | */ 22 | type IsLessZero = IsZero extends true ? false : common.Not> 23 | 24 | /** 25 | * number类型是否是小数 26 | */ 27 | type IsFloat< 28 | N extends NumberLike, 29 | OnlyCheckPoint extends boolean = true 30 | > = string.Stringify extends `${infer Left}${"."}${infer Right}` 31 | ? OnlyCheckPoint extends true 32 | ? true 33 | : common.Not, "0">> 34 | : false 35 | 36 | type ParseFloatRemoveZeroHelper = Int extends `${infer Left}0` ? ParseFloatRemoveZeroHelper : Int 37 | 38 | 39 | type ParseFloatHelper< 40 | N extends NumberLike, 41 | StrN extends NumberLike = string.Stringify, 42 | NIsFloat = IsFloat, 43 | NLeftRight extends [string, string] = StrN extends `${infer Int}.${infer Float}` ? [Int, Float] : [string, string], 44 | NRightWithoutTailZero extends string = ParseFloatRemoveZeroHelper, 45 | ProcessedStr = NIsFloat extends true ? NRightWithoutTailZero extends '' ? NLeftRight[0] : `${NLeftRight[0]}.${NRightWithoutTailZero}` : StrN 46 | > = ProcessedStr extends `${infer Int extends number}` ? Int : never 47 | 48 | // 包含小数点结果最大17位,输入的小数部分的末尾可以加很多0 49 | type ParseFloat = ParseFloatHelper 50 | 51 | /** 52 | * number类型是否是整数 53 | */ 54 | type IsInt< 55 | N extends NumberLike, 56 | OnlyCheckPoint extends boolean = true 57 | > = common.Not> 58 | 59 | /** 60 | * 两个number类型是否相等 61 | */ 62 | type IsEqual< 63 | L extends NumberLike, 64 | R extends NumberLike, 65 | Strict extends boolean = true 66 | > = Strict extends true 67 | ? common.CheckLeftIsExtendsRight 68 | : common.CheckLeftIsExtendsRight, string.Stringify> 69 | 70 | type IsNotEqual< 71 | L extends NumberLike, 72 | R extends NumberLike, 73 | Strict extends boolean = true 74 | > = common.Not> 75 | 76 | type IntAddSingleHepler = [ 77 | ...array.GetTuple, 78 | ...array.GetTuple 79 | ]["length"] 80 | 81 | /** 82 | * 正整数(和0)加法,A1,A2最大999 83 | * @see https://juejin.cn/post/7050893279818317854#heading-8 84 | */ 85 | type IntAddSimple = IntAddSingleHepler< 86 | N1, 87 | N2 88 | > extends number 89 | ? IntAddSingleHepler 90 | : number 91 | 92 | type GetLeftRestAndRight = SN extends `${infer S}${Numbers}` ? SN extends `${S}${infer Last extends `${Numbers}`}` ? [S, Last] : never : never 93 | 94 | type IntIncreaseStepHelper< 95 | LeftRest, 96 | Last extends `${Numbers}`, 97 | Cache extends string = '', 98 | Add extends `${Numbers}` = '1', 99 | ResultInfo extends AddMap[number][number] = AddMap[Last][Add], 100 | Next extends [string, `${Numbers}`] = GetLeftRestAndRight, 101 | > = LeftRest extends `${Numbers}` | '' 102 | ? `${LeftRest extends '' 103 | ? '' 104 | : LeftRest extends `${Numbers}` 105 | ? `${AddMap[LeftRest][Add]['add'] extends '1' ? '1' : ''}${AddMap[LeftRest][Add]['result']}` 106 | : ''}${ResultInfo['result']}${Cache}` 107 | : IntIncreaseStepHelper< 108 | Next[0], 109 | Next[1], 110 | `${ResultInfo['result']}${Cache}`, 111 | ResultInfo['add'] 112 | > 113 | 114 | type a = IntIncreaseStepHelper[0], GetLeftRestAndRight<'99'>[1]> 115 | /** 116 | * SN 12345 L 1 R 2345 117 | * SN 2345 L 2 R 345 118 | * SN 345 L 3 R 45 119 | * SN 45 L 4 R 5 120 | */ 121 | 122 | 123 | type IntIncreaseHelper< 124 | N extends NumberLike, 125 | StrN extends NumberLike = string.Stringify, 126 | NIsFloat = IsFloat, 127 | LeftRestAndRight extends [string, `${Numbers}`] = GetLeftRestAndRight, 128 | Result = NIsFloat extends true ? never : IntIncreaseStepHelper 129 | > = Result extends `${infer R extends number}` ? R : never 130 | 131 | type IntIncrease = IntAddSimple<`${N}`, 1> 132 | // IntIncreaseHelper 133 | 134 | type CompareHelper< 135 | N1 extends number, 136 | N2 extends number, 137 | A1 extends unknown[] = array.GetTuple, 138 | A2 extends unknown[] = array.GetTuple 139 | > = IsNotEqual extends true 140 | ? common.Or, IsZero> extends true 141 | ? IsZero extends true 142 | ? false 143 | : true 144 | : CompareHelper["length"], array.Pop["length"]> 145 | : false 146 | 147 | type Compare = CompareHelper 148 | 149 | type IntMinusSingleAbsHelper< 150 | N1 extends number, 151 | N2 extends number, 152 | A1 extends unknown[] = array.GetTuple, 153 | A2 extends unknown[] = array.GetTuple 154 | > = IsNotEqual extends true 155 | ? common.Or, IsZero> extends true 156 | ? IsZero extends true 157 | ? A2["length"] 158 | : A1["length"] 159 | : IntMinusSingleAbsHelper["length"], array.Pop["length"]> 160 | : 0 161 | 162 | type IntMinusSingleAbs< 163 | N1 extends number, 164 | N2 extends number 165 | > = IntMinusSingleAbsHelper 166 | 167 | type GetHalfHelper = IsEqual< 168 | IntAddSimple, 169 | N 170 | > extends true 171 | ? Offset 172 | : IsEqual, 1>, N> extends true 173 | ? IntAddSimple 174 | : GetHalfHelper> 175 | 176 | // 获取当前数的一半 177 | type GetHalf = GetHalfHelper 178 | 179 | /** @see https://juejin.cn/post/6999280101556748295#heading-68 */ 180 | type Map = { 181 | "0": [] 182 | "1": [1] 183 | "2": [...Map["1"], 1] 184 | "3": [...Map["2"], 1] 185 | "4": [...Map["3"], 1] 186 | "5": [...Map["4"], 1] 187 | "6": [...Map["5"], 1] 188 | "7": [...Map["6"], 1] 189 | "8": [...Map["7"], 1] 190 | "9": [...Map["8"], 1] 191 | } 192 | 193 | type Make10Array = [ 194 | ...T, 195 | ...T, 196 | ...T, 197 | ...T, 198 | ...T, 199 | ...T, 200 | ...T, 201 | ...T, 202 | ...T, 203 | ...T 204 | ] 205 | 206 | type ToNumberHelper< 207 | S extends string, 208 | L extends any[] = [] 209 | > = S extends `${infer F}${infer R}` 210 | ? ToNumberHelper< 211 | R, 212 | [...Make10Array, ...(F extends keyof Map ? Map[F] : never)] 213 | > 214 | : L["length"] 215 | 216 | type ToNumber = ToNumberHelper 217 | 218 | type Numbers = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 219 | 220 | type AdvancedNumericCharacters = 221 | | `${0}.${number}` 222 | | `${Exclude}${number | ""}.${number}` 223 | | `${Exclude}${Numbers | ""}.${number}` 224 | | `${Exclude}${number}` 225 | | `${Numbers}` 226 | 227 | type AddMap = [ 228 | [ 229 | { result: "0"; add: "0" }, // 00 230 | { result: "1"; add: "0" }, // 01 231 | { result: "2"; add: "0" }, // 02 232 | { result: "3"; add: "0" }, // 03 233 | { result: "4"; add: "0" }, // 04 234 | { result: "5"; add: "0" }, // 05 235 | { result: "6"; add: "0" }, // 06 236 | { result: "7"; add: "0" }, // 07 237 | { result: "8"; add: "0" }, // 08 238 | { result: "9"; add: "0" } // 09 239 | ], 240 | [ 241 | { result: "1"; add: "0" }, // 10 242 | { result: "2"; add: "0" }, // 11 243 | { result: "3"; add: "0" }, // 12 244 | { result: "4"; add: "0" }, // 13 245 | { result: "5"; add: "0" }, // 14 246 | { result: "6"; add: "0" }, // 15 247 | { result: "7"; add: "0" }, // 16 248 | { result: "8"; add: "0" }, // 17 249 | { result: "9"; add: "0" }, // 18 250 | { result: "0"; add: "1" } // 19 251 | ], 252 | [ 253 | { result: "2"; add: "0" }, // 20 254 | { result: "3"; add: "0" }, // 21 255 | { result: "4"; add: "0" }, // 22 256 | { result: "5"; add: "0" }, // 23 257 | { result: "6"; add: "0" }, // 24 258 | { result: "7"; add: "0" }, // 25 259 | { result: "8"; add: "0" }, // 26 260 | { result: "9"; add: "0" }, // 27 261 | { result: "0"; add: "1" }, // 28 262 | { result: "1"; add: "1" } // 29 263 | ], 264 | [ 265 | { result: "3"; add: "0" }, // 30 266 | { result: "4"; add: "0" }, // 31 267 | { result: "5"; add: "0" }, // 32 268 | { result: "6"; add: "0" }, // 33 269 | { result: "7"; add: "0" }, // 34 270 | { result: "8"; add: "0" }, // 35 271 | { result: "9"; add: "0" }, // 36 272 | { result: "0"; add: "1" }, // 37 273 | { result: "1"; add: "1" }, // 38 274 | { result: "2"; add: "1" } // 39 275 | ], 276 | [ 277 | { result: "4"; add: "0" }, // 40 278 | { result: "5"; add: "0" }, // 41 279 | { result: "6"; add: "0" }, // 42 280 | { result: "7"; add: "0" }, // 43 281 | { result: "8"; add: "0" }, // 44 282 | { result: "9"; add: "0" }, // 45 283 | { result: "0"; add: "1" }, // 46 284 | { result: "1"; add: "1" }, // 47 285 | { result: "2"; add: "1" }, // 48 286 | { result: "3"; add: "1" } // 49 287 | ], 288 | [ 289 | { result: "5"; add: "0" }, // 50 290 | { result: "6"; add: "0" }, // 51 291 | { result: "7"; add: "0" }, // 52 292 | { result: "8"; add: "0" }, // 53 293 | { result: "9"; add: "0" }, // 54 294 | { result: "0"; add: "1" }, // 55 295 | { result: "1"; add: "1" }, // 56 296 | { result: "2"; add: "1" }, // 57 297 | { result: "3"; add: "1" }, // 58 298 | { result: "4"; add: "1" } // 59 299 | ], 300 | [ 301 | { result: "6"; add: "0" }, // 60 302 | { result: "7"; add: "0" }, // 61 303 | { result: "8"; add: "0" }, // 62 304 | { result: "9"; add: "0" }, // 63 305 | { result: "0"; add: "1" }, // 64 306 | { result: "1"; add: "1" }, // 65 307 | { result: "2"; add: "1" }, // 66 308 | { result: "3"; add: "1" }, // 67 309 | { result: "4"; add: "1" }, // 68 310 | { result: "5"; add: "1" } // 69 311 | ], 312 | [ 313 | { result: "7"; add: "0" }, // 70 314 | { result: "8"; add: "0" }, // 71 315 | { result: "9"; add: "0" }, // 72 316 | { result: "0"; add: "1" }, // 73 317 | { result: "1"; add: "1" }, // 74 318 | { result: "2"; add: "1" }, // 75 319 | { result: "3"; add: "1" }, // 76 320 | { result: "4"; add: "1" }, // 77 321 | { result: "5"; add: "1" }, // 78 322 | { result: "6"; add: "1" } // 79 323 | ], 324 | [ 325 | { result: "8"; add: "0" }, // 80 326 | { result: "9"; add: "0" }, // 81 327 | { result: "0"; add: "1" }, // 82 328 | { result: "1"; add: "1" }, // 83 329 | { result: "2"; add: "1" }, // 84 330 | { result: "3"; add: "1" }, // 85 331 | { result: "4"; add: "1" }, // 86 332 | { result: "5"; add: "1" }, // 87 333 | { result: "6"; add: "1" }, // 88 334 | { result: "7"; add: "1" } // 89 335 | ], 336 | [ 337 | { result: "9"; add: "0" }, // 90 338 | { result: "0"; add: "1" }, // 91 339 | { result: "1"; add: "1" }, // 92 340 | { result: "2"; add: "1" }, // 93 341 | { result: "3"; add: "1" }, // 94 342 | { result: "4"; add: "1" }, // 95 343 | { result: "5"; add: "1" }, // 96 344 | { result: "6"; add: "1" }, // 97 345 | { result: "7"; add: "1" }, // 98 346 | { result: "8"; add: "1" } // 99 347 | ] 348 | ] 349 | 350 | type SplitByPoint = string.Includes< 351 | S, 352 | "." 353 | > extends true 354 | ? string.Split 355 | : [S, "0"] 356 | 357 | type AddHelperSplitToArr< 358 | S1 extends AdvancedNumericCharacters, 359 | S2 extends AdvancedNumericCharacters, 360 | Result = [SplitByPoint, SplitByPoint] 361 | > = Result extends [[`${number}`, `${number}`], [`${number}`, `${number}`]] 362 | ? Result 363 | : never 364 | 365 | type AddFillZeroHelper< 366 | Data extends [[`${number}`, `${number}`], [`${number}`, `${number}`]], 367 | Result = [ 368 | [ 369 | string.PadStart, "0">, 370 | string.PadEnd, "0"> 371 | ], 372 | [ 373 | string.PadStart, "0">, 374 | string.PadEnd, "0"> 375 | ] 376 | ] 377 | > = Result extends [[`${number}`, `${number}`], [`${number}`, `${number}`]] 378 | ? Result 379 | : never 380 | 381 | type AddReverseData< 382 | Data extends [[`${number}`, `${number}`], [`${number}`, `${number}`]], 383 | Result = [ 384 | [ 385 | array.Reverse>, 386 | array.Reverse> 387 | ], 388 | [ 389 | array.Reverse>, 390 | array.Reverse> 391 | ] 392 | ] 393 | > = Result extends [ 394 | [`${Numbers}`[], `${Numbers}`[]], 395 | [`${Numbers}`[], `${Numbers}`[]] 396 | ] 397 | ? Result 398 | : never 399 | 400 | type StepAdderHelper< 401 | DataLeft extends `${Numbers}`[], 402 | DataRight extends `${Numbers}`[], 403 | Curry extends `${Numbers}` = `${0}`, 404 | Offset extends number = 0, 405 | ResultCache extends `${number}`[] = [], 406 | NextOffset extends number = number.IntAddSimple, 407 | Current extends AddMap[Numbers][Numbers] = AddMap[DataLeft[Offset]][DataRight[Offset]], 408 | CurrentWidthPreCurry extends `${Numbers}` = AddMap[Current["result"]][Curry]["result"] 409 | > = DataLeft["length"] extends DataRight["length"] 410 | ? `${Offset}` extends `${DataLeft["length"]}` 411 | ? ResultCache 412 | : StepAdderHelper< 413 | DataLeft, 414 | DataRight, 415 | Current["add"], 416 | NextOffset, 417 | common.And< 418 | number.IsEqual, 419 | number.IsEqual<`${NextOffset}`, `${DataLeft["length"]}`> 420 | > extends true 421 | ? array.Push<["10", ...ResultCache], CurrentWidthPreCurry> 422 | : array.Push 423 | > 424 | : never 425 | 426 | type NumbersWidthCurry = Numbers | 10 427 | 428 | type MergeResultHelper< 429 | Data extends [ 430 | [`${Numbers}`[], `${Numbers}`[]], 431 | [`${Numbers}`[], `${Numbers}`[]] 432 | ], 433 | LeftInt extends `${Numbers}`[] = Data[0][0], 434 | LeftFloat extends `${Numbers}`[] = Data[0][1], 435 | RightInt extends `${Numbers}`[] = Data[1][0], 436 | RightFloat extends `${Numbers}`[] = Data[1][1], 437 | FloatAdded extends `${NumbersWidthCurry}`[] = StepAdderHelper< 438 | LeftFloat, 439 | RightFloat 440 | >, 441 | FloatHasCurry extends boolean = FloatAdded[0] extends "10" ? true : false, 442 | DeleteCurryFloatResult extends unknown[] = FloatHasCurry extends true 443 | ? array.Shift 444 | : FloatAdded, 445 | IntAdded extends `${NumbersWidthCurry}`[] = StepAdderHelper< 446 | LeftInt, 447 | RightInt, 448 | FloatHasCurry extends true ? `1` : "0" 449 | >, 450 | IntHasCurry extends boolean = IntAdded[0] extends "10" ? true : false, 451 | DeleteCurryIntResult extends unknown[] = IntHasCurry extends true 452 | ? array.Shift 453 | : IntAdded, 454 | ResultReversed = array.Reverse< 455 | LeftFloat["length"] extends 0 456 | ? DeleteCurryIntResult 457 | : array.Concat< 458 | [...DeleteCurryFloatResult, "."], 459 | [...DeleteCurryIntResult] 460 | > 461 | >, 462 | FloatResult = array.Join< 463 | ResultReversed extends string[] 464 | ? IntHasCurry extends true 465 | ? ["1", ...ResultReversed] 466 | : ResultReversed 467 | : never, 468 | "" 469 | > 470 | > = FloatResult 471 | 472 | type Add< 473 | S1 extends AdvancedNumericCharacters, 474 | S2 extends AdvancedNumericCharacters 475 | > = MergeResultHelper< 476 | AddReverseData>> 477 | > 478 | 479 | export type { 480 | NumberLike, 481 | IsZero, 482 | IsOverZero, 483 | IsLessZero, 484 | IsFloat, 485 | IsInt, 486 | IsEqual, 487 | IsNotEqual, 488 | IntIncrease, 489 | IntAddSimple, 490 | IntMinusSingleAbs, 491 | Compare, 492 | GetHalf, 493 | ToNumber, 494 | Add, 495 | ParseFloat 496 | } 497 | --------------------------------------------------------------------------------