Co-Pilot / 辅助式
更新于 24 days ago

inferred-types

Iinocan-group
0.0k
inocan-group/inferred-types
78
Agent 评分

💡 摘要

一个 TypeScript 工具库,通过强类型和运行时函数增强类型安全性和运行时一致性。

🎯 适合人群

TypeScript 开发者专注于类型安全的软件工程师使用 TypeScript 的前端开发者利用 TypeScript 的后端开发者监督 TypeScript 项目的技术负责人

🤖 AI 吐槽:这就像 TypeScript 的瑞士军刀,但刀片更少,类型安全性更高。

安全分析低风险

该库似乎不执行 shell 命令或访问网络,但它依赖于 TypeScript 类型和运行时函数,如果使用不当可能会引入风险。确保对输入进行适当验证,以减轻潜在的类型相关漏洞。

logo

Overview

A collection of Typescript utilities which try to preserve as much strong and narrow typing as is possible. In many cases, these type utilities will be paired with a runtime function which provides a runtime mirror to help keep both design time types and runtime values in sync.

All types -- as well as any pairing runtime functions -- are intended to be "self documenting" as much as is possible. This means that they will at least have a description comment which your editor should expose as a popover. In some cases, there are also code examples included in these comments to further flesh out intended use.

To keep things DRY, the documentation here will be kept to a minimum. This README is intended more as a high level introduction of scope and structure of this repo than documentation.

Directory Structure

Under the src/ folder you'll find the the following subdirectories:

  • constants - a set of runtime constants that can provide utility to both runtime functions as well as provide foundation for enumerated types.
  • types - this folder represents the heart of the repo in the form of type utilities and is further broken down by an attempt at functional classification that hopefully aides somewhat in feature discovery.
  • runtime - this is where you'll find runtime functions which mutate state while taking care to provide as much as type information that compliments the runtime environment as is possible.

Runtime synchronization with Types

You will find many runtime functions like ensureLeading(str, substring) which have a similarly named type (in this case EnsureLeading<TStr, TSubstring>). This is no accident and at some future point there may even be something approximating 1:1 parity.

This connection between the type system and the runtime environment allows both a harmonization of variables across both environments and helps to ensure their consistency but it the runtime environment also often really needs strong type utilities to extract out narrow type definitions in the runtime environment.

Examples

What follows is not meant to be comprehensive set of examples but rather just a sampling that hopefully gives some perspective on the breadth of scope of this library.

String Literals

Casing Conventions

  • use PascalCase<T>, CamelCase<T>, SnakeCase<T>, and KebabCase<T> to convert a string to one of several familiar naming conventions
  • use AllCaps<T> to make all alphanumeric characters into their uppercase variant

Pluralization

Convert the type and value of a variable from it's singular form to it's plural form:

import { pluralize } from "inferred-types"; // "people" const people = pluralize("person");

Note: not only does this utility provide all major grammatical rules used in conversion but has a dictionary of common exceptions it will use too.

Consistency with Ensure/Strip utilities

  • it's often desirable to ensure that a string starts with or ends with a given string

  • the inverse can also be useful (aka, to ensure a string does not start or end with a given string literal)

  • this library provides EnsureLeading, EnsureTrailing, StripLeading, and StripTrailing utilities to meet these type needs

    import type { EnsureLeading } from "inferred-types"; // "start-${string}" type T1 = EnsureLeading<string, "start-">; // "start-with" type T2 = EnsureLeading<"start-with", "start-">; // "start-with" type T3 = EnsureLeading<"with", "start-">;

Character Sets

  • types like Alpha, NumericChar, Whitespace, Consonants, etc. try to represent character set building blocks that we may have to isolate on for our own types definitions

Data Patterns

  • types like Url, IpAddress, CSV, DotPath, Hexadecimal, ZipCode, and DomainName attempt to provide an out of the box type for common data structure patterns we find in the real world
  • ISO3166 support (aka, countries):
    • Iso3166_Alpha2, Iso3166_Alpha3, ...
    • isIso3166Alpha2(), isIsoAlpha3(), type guards ...
  • ISO8601 support (aka, datetime)
    • Iso8601DateTime, Iso8601Date, Iso8601Time, ...
    • isIsoDateTime(), isIsoDate(), isIsoTime(), ...

For more info see URLs, Date and Time, and

String Interpolation

const matcher = infer("{{ string }} is a {{ infer foo }} utility, that {{ infer bar }}"); // { foo: "fancy"; bar: "thinks it's better than you!"} const fooBar = matcher("infer is a fancy utility, that thinks it's better than you!")

Numeric Literals

  • use the Add<A,B>, Subtract<A,B>, Increment<T>, Decrement<T> utilities to work with numeric types (or even numeric string literals)
  • get the length of a string or tuple with the Length<T> utility
  • ensure an integer value with Integer<T>; ensure a float value with Float<T>
  • compare numeric literals with LessThan<A,B>, LessThanOrEqual<A,B>, and GreaterThan<A,B>
  • ensure a positive number with Abs<T>
  • details on numeric types

Lists

  • Use AfterFirst, First, Last to index into a tuple / list value
  • Use AsArray<T> to ensure an array value for T
  • Use Flatten<T> to flatten an array
  • Use Slice<T,S,E> to take out a subset of elements in a list
  • Use Reverse to reverse a list

Object / Dictionaries

Reduce Object to Keys with a knownValue

Assume a base type of Obj:

type Obj = { n1: number; n2: 2; n3: 3; success: true; s1: string; s2: "hello"; }

We can get a union of string literals representing the keys on the object whose value extends some value:

import type { KeysWithValue, KeysWithoutValue } from "inferred-types"; // "s1" | "s2" type S = KeysWithValue<Obj, string>; // "success" | "n1" | "n2" type N = KeysWithoutValue<Obj, string>;

though less used, you can also use KeysEqualValue and KeysNotEqualValue for equality matching

If you'd prefer to mutate the object's type rather than just identify the keys which extend a value you can do this with: WithValue and WithoutValue:

import type { WithValue, WithoutValue } from "inferred-types"; // { s1: string; s2: "hello" } type S = WithValue<Obj, string>; // { success: true; n1: number; n2: 2; n3: 3 } type N = WithoutValue<Obj, string>;

And at runtime:

// { foo: "hi" } const foo = withoutValue("number")({ foo: "hi", bar: 42, baz: 99 }); // { bar: 42 } const bar = withoutValue("number(42,55,66)")({ foo: "hi", bar: 42, baz: 99 }); // { foo: "hi", bar: 42 } const fooBar = withoutKeys("baz")({ foo: "hi", bar: 42, baz: 99 }); // { foo: "hi", bar: 42 } const fooBar2 = withKeys("foo", "bar")({ foo: "hi", bar: 42, baz: 99 })

Reduce Object's to only Required or Optional keys

type Obj = { foo: string; bar?: string; baz?: number }; // "foo" type ReqKeys = RequiredKeys<Obj>; // ["foo"] type ReqKeyTup = RequiredKeysTuple<Obj>; // "bar" | "baz" type OptKeys = OptionalKeys<Obj>; // ["bar", "baz"] type OptKeyTup = OptionalKeysTuple<Obj>; type Reduced =

Contributing

If you are using this library and would like to take the next step of contributing; that effort is welcome but please do make sure to always provide both runtime and type tests for any code changes which you submit as a pull request.

See the plentiful examples that exist under the tests/ folder for inspiration.

Note: as of 2024 I'm also starting to add "type performance" tests; not an absolute requirement but in general adding something like you'll find in the benches/ folder for any new type utility would be appreciated.

Licensing

This repo is offered under the highly permissive MIT license.

五维分析
清晰度8/10
创新性7/10
实用性9/10
完整性7/10
可维护性8/10
优缺点分析

优点

  • 强大的类型安全特性
  • 用于一致性的运行时函数
  • 自文档化的类型
  • 类型工具的 DRY 方法

缺点

  • 文档有限
  • 复杂性可能让初学者感到困惑
  • 可能的性能开销
  • 并不全面适用于所有用例

相关技能

openai-agents-js

A
toolCo-Pilot / 辅助式
84/ 100

“看起来很能打,但别让配置把人劝退。”

mastra

A
toolCode Lib / 代码库
84/ 100

“这是 AI 智能体的瑞士军刀,但你需要一本说明书才能搞清楚哪片刀片是用来切 LLM 的,哪片是用来撬开顽固的工作流的。”

basilic

A
toolCo-Pilot / 辅助式
82/ 100

“看起来很能打,但别让配置把人劝退。”

免责声明:本内容来源于 GitHub 开源项目,仅供展示和评分分析使用。

版权归原作者所有 inocan-group.