Skip to content

Commit

Permalink
Esm
Browse files Browse the repository at this point in the history
  • Loading branch information
sinclairzx81 committed Nov 28, 2023
1 parent 9105f7c commit 2cf0546
Show file tree
Hide file tree
Showing 14 changed files with 562 additions and 577 deletions.
23 changes: 20 additions & 3 deletions src/type/helpers/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import type { TSchema } from '../schema/index'
import type { TProperties } from '../object/index'
import type { TNever } from '../never/index'
// ------------------------------------------------------------------
// Helper: Core
// Helper: Common
// ------------------------------------------------------------------
export type TupleToIntersect<T extends any[]> = T extends [infer I] ? I : T extends [infer I, ...infer R] ? I & TupleToIntersect<R> : never
export type TupleToUnion<T extends any[]> = { [K in keyof T]: T[K] }[number]
Expand All @@ -43,9 +43,26 @@ export type Evaluate<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
export type Ensure<T> = T extends infer U ? U : never
export type EmptyString = ''
export type ZeroString = '0'

// ------------------------------------------------------------------
// Helper: Asserts
// Helper: Increment
// ------------------------------------------------------------------
export type IncrementBase = { m: '9'; t: '01'; '0': '1'; '1': '2'; '2': '3'; '3': '4'; '4': '5'; '5': '6'; '6': '7'; '7': '8'; '8': '9'; '9': '0' }
export type IncrementTake<T extends keyof IncrementBase> = IncrementBase[T]
export type IncrementStep<T extends string> = T extends IncrementBase['m']
? IncrementBase['t']
: T extends `${infer L extends keyof IncrementBase}${infer R}`
? L extends IncrementBase['m']
? `${IncrementTake<L>}${IncrementStep<R>}`
: `${IncrementTake<L>}${R}`
: never
export type IncrementReverse<T extends string> = T extends `${infer L}${infer R}` ? `${IncrementReverse<R>}${L}` : T
export type Increment<T extends string> = IncrementReverse<IncrementStep<IncrementReverse<T>>>
/** Increments the given string value + 1 */
export function Increment<T extends string>(T: T): Increment<T> {
return (parseInt(T) + 1).toString() as Increment<T>
}
// ------------------------------------------------------------------
// Helper: Type Asserts
// ------------------------------------------------------------------
export type AssertProperties<T> = T extends TProperties ? T : TProperties
export type AssertRest<T, E extends TSchema[] = TSchema[]> = T extends E ? T : []
Expand Down
39 changes: 0 additions & 39 deletions src/type/increment/increment.ts

This file was deleted.

5 changes: 2 additions & 3 deletions src/type/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ THE SOFTWARE.
// export { type TSchema } from './schema/index'
// export { type Static, type StaticDecode, type StaticEncode } from './static/index'
// export { type TString, String } from './string/index'

// export { type TSymbol, Symbol } from './symbol/index'

// export { type TTemplateLiteral, type TTemplateLiteralKind, TemplateLiteral } from './template-literal/index'
// export { type TTransform, Transform } from './transform/index'
// export { type TTuple, Tuple } from './tuple/index'
Expand Down Expand Up @@ -119,7 +119,6 @@ export * from './extract/index'
export * from './function/index'
export * from './guard/index'
export * from './helpers/index'
export * from './increment/index'
export * from './indexed/index'
export * from './instance-type/index'
export * from './integer/index'
Expand All @@ -128,14 +127,14 @@ export * from './intrinsic/index'
export * from './iterator/index'
export * from './keyof/index'
export * from './literal/index'
export * from './logic/index'
export * from './modifiers/index'
export * from './never/index'
export * from './not/index'
export * from './null/index'
export * from './number/index'
export * from './object/index'
export * from './omit/index'
export * from './operators/index'
export * from './optional/index'
export * from './parameters/index'
export * from './partial/index'
Expand Down
222 changes: 113 additions & 109 deletions src/type/intrinsic/intrinsic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,142 +30,146 @@ import type { TSchema, SchemaOptions } from '../schema/index'
import { type TTemplateLiteral, type TTemplateLiteralKind, TemplateLiteral, TemplateLiteralParseExact, IsTemplateLiteralFinite, TemplateLiteralGenerate } from '../template-literal/index'
import { type TLiteral, type TLiteralValue, Literal } from '../literal/index'
import { type TUnion, Union } from '../union/index'
import { CloneType } from '../clone/type'
import { TTemplateLiteral as IsTemplateLiteralType, TUnion as IsUnionType, TLiteral as IsLiteralType } from '../guard/type'
import { CloneType } from '../clone/type'

// ----------------------------------------------------------------
// Apply
// ----------------------------------------------------------------
function ApplyUncapitalize(value: string): string {
const [first, rest] = [value.slice(0, 1), value.slice(1)]
return [first.toLowerCase(), rest].join('')
}
function ApplyCapitalize(value: string): string {
const [first, rest] = [value.slice(0, 1), value.slice(1)]
return [first.toUpperCase(), rest].join('')
}
function ApplyUppercase(value: string): string {
return value.toUpperCase()
}
function ApplyLowercase(value: string): string {
return value.toLowerCase()
}
// ----------------------------------------------------------------
// IntrinsicMode
// ----------------------------------------------------------------
type IntrinsicMode = 'Uppercase' | 'Lowercase' | 'Capitalize' | 'Uncapitalize'
// ----------------------------------------------------------------
// IntrinsicTemplateLiteral
// ----------------------------------------------------------------
// prettier-ignore
export namespace IntrinsicResolver {
// ----------------------------------------------------------------
// Operations
// ----------------------------------------------------------------
function Uncapitalize(value: string): string {
const [first, rest] = [value.slice(0, 1), value.slice(1)]
return [first.toLowerCase(), rest].join('')
}
function Capitalize(value: string): string {
const [first, rest] = [value.slice(0, 1), value.slice(1)]
return [first.toUpperCase(), rest].join('')
}
function Uppercase(value: string): string {
return value.toUpperCase()
}
function Lowercase(value: string): string {
return value.toLowerCase()
}
// ----------------------------------------------------------------
// IntrinsicTemplateLiteral
// ----------------------------------------------------------------
export type IntrinsicMode = 'Uppercase' | 'Lowercase' | 'Capitalize' | 'Uncapitalize'
// ----------------------------------------------------------------
// IntrinsicTemplateLiteral
// ----------------------------------------------------------------
// prettier-ignore
export type FromTemplateLIteral<T extends TTemplateLiteralKind[], M extends IntrinsicMode> =
M extends IntrinsicMode ?
T extends [infer L extends TTemplateLiteralKind, ...infer R extends TTemplateLiteralKind[]]
? [Resolve<L, M>, ...FromTemplateLIteral<R, M>]
: T
: T
function FromTemplateLiteral<T extends TTemplateLiteralKind[], M extends IntrinsicMode>(schema: TTemplateLiteral, mode: IntrinsicMode): FromTemplateLIteral<T, M> {
// note: template literals require special runtime handling as they are encoded in string patterns.
// This diverges from the mapped type which would otherwise map on the template literal kind.
const expression = TemplateLiteralParseExact(schema.pattern)
const finite = IsTemplateLiteralFinite(expression)
if (!finite) return { ...schema, pattern: FromLiteralValue(schema.pattern, mode) } as any
const strings = [...TemplateLiteralGenerate(expression)]
const literals = strings.map((value) => Literal(value))
const mapped = FromRest(literals as any, mode)
const union = Union(mapped)
return TemplateLiteral([union]) as unknown as FromTemplateLIteral<T, M>
}
// ----------------------------------------------------------------
// IntrinsicLiteral
// ----------------------------------------------------------------
// prettier-ignore
export type FromLiteralValue<T, M extends IntrinsicMode> = (
T extends string ?
M extends 'Uncapitalize' ? Uncapitalize<T> :
M extends 'Capitalize' ? Capitalize<T> :
M extends 'Uppercase' ? Uppercase<T> :
M extends 'Lowercase' ? Lowercase<T> :
string
type FromTemplateLiteral<T extends TTemplateLiteralKind[], M extends IntrinsicMode> =
M extends IntrinsicMode ?
T extends [infer L extends TTemplateLiteralKind, ...infer R extends TTemplateLiteralKind[]]
? [IntrinsicResolve<L, M>, ...FromTemplateLiteral<R, M>]
: T
: T
function FromTemplateLiteral<T extends TTemplateLiteralKind[], M extends IntrinsicMode>(schema: TTemplateLiteral, mode: IntrinsicMode): FromTemplateLiteral<T, M> {
// note: template literals require special runtime handling as they are encoded in string patterns.
// This diverges from the mapped type which would otherwise map on the template literal kind.
const expression = TemplateLiteralParseExact(schema.pattern)
const finite = IsTemplateLiteralFinite(expression)
if (!finite) return { ...schema, pattern: FromLiteralValue(schema.pattern, mode) } as any
const strings = [...TemplateLiteralGenerate(expression)]
const literals = strings.map((value) => Literal(value))
const mapped = FromRest(literals as any, mode)
const union = Union(mapped)
return TemplateLiteral([union]) as unknown as FromTemplateLiteral<T, M>
}
// ----------------------------------------------------------------
// FromLiteralValue
// ----------------------------------------------------------------
// prettier-ignore
type FromLiteralValue<T, M extends IntrinsicMode> = (
T extends string ?
M extends 'Uncapitalize' ? Uncapitalize<T> :
M extends 'Capitalize' ? Capitalize<T> :
M extends 'Uppercase' ? Uppercase<T> :
M extends 'Lowercase' ? Lowercase<T> :
string
: T
)
// prettier-ignore
function FromLiteralValue(value: TLiteralValue, mode: IntrinsicMode) {
return (
typeof value === 'string' ? (
mode === 'Uncapitalize' ? ApplyUncapitalize(value) :
mode === 'Capitalize' ? ApplyCapitalize(value) :
mode === 'Uppercase' ? ApplyUppercase(value) :
mode === 'Lowercase' ? ApplyLowercase(value) :
value
) : value.toString()
)
function FromLiteralValue(value: TLiteralValue, mode: IntrinsicMode) {
return (
typeof value === 'string' ? (
mode === 'Uncapitalize' ? Uncapitalize(value) :
mode === 'Capitalize' ? Capitalize(value) :
mode === 'Uppercase' ? Uppercase(value) :
mode === 'Lowercase' ? Lowercase(value) :
value
) : value.toString()
)
}
// ----------------------------------------------------------------
// FromRest
// ----------------------------------------------------------------
// prettier-ignore
export type FromRest<T extends TSchema[], M extends IntrinsicMode> =
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? [Resolve<L, M>, ...FromRest<R, M>]
: []
function FromRest<T extends TSchema[], M extends IntrinsicMode>(T: [...T], mode: M): FromRest<T, M> {
const [L, ...R] = T
return (
T.length > 0
? [Resolve(L, mode), ...FromRest(R, mode)]
: []
) as FromRest<T, M>
}
// ----------------------------------------------------------------
// Resolve
// ----------------------------------------------------------------
// prettier-ignore
export type Resolve<T extends TSchema, M extends IntrinsicMode> =
T extends TTemplateLiteral<infer S> ? TTemplateLiteral<FromTemplateLIteral<S, M>> :
T extends TUnion<infer S> ? TUnion<FromRest<S, M>> :
T extends TLiteral<infer S> ? TLiteral<FromLiteralValue<S, M>> :
T
/** Applies an intrinsic string manipulation to the given type. */
export function Resolve<T extends TSchema, M extends IntrinsicMode>(schema: T, mode: M): Resolve<T, M> {
return (
IsTemplateLiteralType(schema) ? FromTemplateLiteral(schema, mode) :
IsUnionType(schema) ? Union(FromRest(schema.anyOf, mode)) :
IsLiteralType(schema) ? Literal(FromLiteralValue(schema.const, mode)) :
schema
) as Resolve<T, M>
}
}
// ----------------------------------------------------------------
// FromRest
// ----------------------------------------------------------------
// prettier-ignore
type FromRest<T extends TSchema[], M extends IntrinsicMode> =
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? [IntrinsicResolve<L, M>, ...FromRest<R, M>]
: []
function FromRest<T extends TSchema[], M extends IntrinsicMode>(T: [...T], mode: M): FromRest<T, M> {
const [L, ...R] = T
return (T.length > 0 ? [IntrinsicResolve(L, mode), ...FromRest(R, mode)] : []) as FromRest<T, M>
}
// ----------------------------------------------------------------
// Resolve
// ----------------------------------------------------------------
// prettier-ignore
export type IntrinsicResolve<T extends TSchema, M extends IntrinsicMode> =
T extends TTemplateLiteral<infer S> ? TTemplateLiteral<FromTemplateLiteral<S, M>> :
T extends TUnion<infer S> ? TUnion<FromRest<S, M>> :
T extends TLiteral<infer S> ? TLiteral<FromLiteralValue<S, M>> :
T
/** Applies an intrinsic string manipulation to the given type. */
// prettier-ignore
export function IntrinsicResolve<T extends TSchema, M extends IntrinsicMode>(schema: T, mode: M): IntrinsicResolve<T, M> {
return (
IsTemplateLiteralType(schema) ? FromTemplateLiteral(schema, mode) :
IsUnionType(schema) ? Union(FromRest(schema.anyOf, mode)) :
IsLiteralType(schema) ? Literal(FromLiteralValue(schema.const, mode)) :
schema
) as IntrinsicResolve<T, M>
}

// ------------------------------------------------------------------
// TUncapitalize
// ------------------------------------------------------------------
export type TUncapitalize<T extends TSchema> = IntrinsicResolver.Resolve<T, 'Uncapitalize'>
// prettier-ignore
export type TUncapitalize<T extends TSchema> = IntrinsicResolve<T, 'Uncapitalize'>
/** `[Json]` Intrinsic function to Uncapitalize LiteralString types */
// prettier-ignore
export function Uncapitalize<T extends TSchema>(T: T, options: SchemaOptions = {}): TUncapitalize<T> {
return CloneType(IntrinsicResolver.Resolve(T, 'Uncapitalize'), options)
return CloneType(IntrinsicResolve(T, 'Uncapitalize'), options)
}
// ------------------------------------------------------------------
// TUppercase
// ------------------------------------------------------------------
export type TUppercase<T extends TSchema> = IntrinsicResolver.Resolve<T, 'Uppercase'>
// prettier-ignore
export type TUppercase<T extends TSchema> = IntrinsicResolve<T, 'Uppercase'>
/** `[Json]` Intrinsic function to Uppercase LiteralString types */
// prettier-ignore
export function Uppercase<T extends TSchema>(T: T, options: SchemaOptions = {}): TUppercase<T> {
return CloneType(IntrinsicResolver.Resolve(T, 'Uppercase'), options)
return CloneType(IntrinsicResolve(T, 'Uppercase'), options)
}
// ------------------------------------------------------------------
// TLowercase
// ------------------------------------------------------------------
export type TLowercase<T extends TSchema> = IntrinsicResolver.Resolve<T, 'Lowercase'>
// prettier-ignore
export type TLowercase<T extends TSchema> = IntrinsicResolve<T, 'Lowercase'>
/** `[Json]` Intrinsic function to Lowercase LiteralString types */
// prettier-ignore
export function Lowercase<T extends TSchema>(T: T, options: SchemaOptions = {}): TLowercase<T> {
return CloneType(IntrinsicResolver.Resolve(T, 'Lowercase'), options)
return CloneType(IntrinsicResolve(T, 'Lowercase'), options)
}
// ------------------------------------------------------------------
// TCapitalize
// ------------------------------------------------------------------
export type TCapitalize<T extends TSchema> = IntrinsicResolver.Resolve<T, 'Capitalize'>
// prettier-ignore
export type TCapitalize<T extends TSchema> = IntrinsicResolve<T, 'Capitalize'>
/** `[Json]` Intrinsic function to Capitalize LiteralString types */
// prettier-ignore
export function Capitalize<T extends TSchema>(T: T, options: SchemaOptions = {}): TCapitalize<T> {
return CloneType(IntrinsicResolver.Resolve(T, 'Capitalize'), options)
return CloneType(IntrinsicResolve(T, 'Capitalize'), options)
}
Loading

0 comments on commit 2cf0546

Please sign in to comment.