Comparing version 0.1.7 to 0.1.8
import { Type } from "./Type"; | ||
export declare function intersection<T extends A & B, A, B>(...types: [Type<A>, Type<B>]): Type<T>; | ||
export declare function intersection<T extends A & B, A, B>(typeA: Type<A>, typeB: Type<B>): Type<T>; | ||
export declare function intersection<T extends A & B & C, A, B, C>(typeA: Type<A>, typeB: Type<B>, typeC: Type<C>): Type<T>; | ||
export declare function intersection<T extends A & B & C, A, B, C>(typeA: Type<A>, typeB: Type<B>, typeC: Type<C>): Type<T>; | ||
export declare function intersection<T extends A & B & C & D, A, B, C, D>(typeA: Type<A>, typeB: Type<B>, typeC: Type<C>, typeD: Type<D>): Type<T>; | ||
export declare function intersection<T extends A & B & C & D & E, A, B, C, D, E>(typeA: Type<A>, typeB: Type<B>, typeC: Type<C>, typeD: Type<D>, typeE: Type<E>): Type<T>; | ||
export declare function intersection<T extends A & B & C & D & E & F, A, B, C, D, E, F>(typeA: Type<A>, typeB: Type<B>, typeC: Type<C>, typeD: Type<D>, typeE: Type<E>, typeF: Type<F>): Type<T>; |
@@ -13,2 +13,27 @@ import { Type } from "./Type"; | ||
} | ||
// This seams to be the behavior users describe on stack overflow | ||
// https://stackoverflow.com/questions/59722333/union-and-intersection-of-types | ||
getValue(value) { | ||
return value && typeof value == "object" | ||
? this.types | ||
.slice(1) | ||
.reduce((resolved, type) => this.merge(resolved, type.get(value)), this.types[0].get(value)) | ||
: value; | ||
} | ||
merge(target, source) { | ||
let result = target; | ||
if (Array.isArray(target) && Array.isArray(source)) | ||
result = target.map((item, index) => this.merge(item, source[index])); | ||
else if (target && typeof target == "object" && source && typeof source == "object") | ||
for (const key in source) | ||
if (Object.getOwnPropertyDescriptor(target, key) && | ||
typeof target[key] == "object" && | ||
typeof source[key] == "object") | ||
Object.assign(target, { | ||
[key]: this.merge(target[key], source[key]), | ||
}); | ||
else | ||
Object.assign(target, { [key]: source[key] }); | ||
return result; | ||
} | ||
} | ||
@@ -15,0 +40,0 @@ export function intersection(...types) { |
@@ -6,6 +6,5 @@ import { Type } from "./Type"; | ||
(this.baseType ? `${this.baseType.name} & ` : "") + | ||
JSON.stringify(globalThis.Object.fromEntries(globalThis.Object.entries(this.properties).map(([property, type]) => [ | ||
property, | ||
type.name, | ||
])))); | ||
`{${globalThis.Object.entries(this.properties) | ||
.map(([property, type]) => `${property}: ${type.name}`) | ||
.join(", ")}}`); | ||
this.baseType = baseType; | ||
@@ -12,0 +11,0 @@ this.properties = properties; |
import { Flaw } from "./Flaw" | ||
import { Type } from "./Type" | ||
class IslyIntersection<T extends A & B, A, B> extends Type<T> { | ||
protected readonly types: [Type<A>, Type<B>] | ||
constructor(...types: [Type<A>, Type<B>]) { | ||
class IslyIntersection<T> extends Type<T> { | ||
protected readonly types: Type<unknown>[] | ||
constructor(...types: Type<unknown>[]) { | ||
super(() => types.map(type => type.name).join(" & ")) | ||
@@ -16,7 +16,60 @@ this.types = types | ||
} | ||
//TODO: handle getValue(value) | ||
// This seams to be the behavior users describe on stack overflow | ||
// https://stackoverflow.com/questions/59722333/union-and-intersection-of-types | ||
protected getValue(value: T): T { | ||
return value && typeof value == "object" | ||
? (this.types | ||
.slice(1) | ||
.reduce((resolved, type) => this.merge(resolved, type.get(value)), this.types[0].get(value)) as T) | ||
: value | ||
} | ||
private merge<Target, Source>(target: Target, source: Source): Target & Source { | ||
let result = target as Target & Source | ||
if (Array.isArray(target) && Array.isArray(source)) | ||
result = target.map((item, index) => this.merge(item, source[index])) as Source & Target | ||
else if (target && typeof target == "object" && source && typeof source == "object") | ||
for (const key in source) | ||
if ( | ||
Object.getOwnPropertyDescriptor(target, key) && | ||
typeof target[key as string as keyof typeof target] == "object" && | ||
typeof source[key] == "object" | ||
) | ||
Object.assign(target, { | ||
[key]: this.merge(target[key as string as keyof typeof target], source[key]), | ||
}) | ||
else | ||
Object.assign(target, { [key]: source[key] }) | ||
return result | ||
} | ||
} | ||
export function intersection<T extends A & B, A, B>(...types: [Type<A>, Type<B>]): Type<T> { | ||
return new IslyIntersection<T, A, B>(...types) | ||
export function intersection<T extends A & B, A, B>(typeA: Type<A>, typeB: Type<B>): Type<T> | ||
export function intersection<T extends A & B & C, A, B, C>(typeA: Type<A>, typeB: Type<B>, typeC: Type<C>): Type<T> | ||
export function intersection<T extends A & B & C, A, B, C>(typeA: Type<A>, typeB: Type<B>, typeC: Type<C>): Type<T> | ||
export function intersection<T extends A & B & C & D, A, B, C, D>( | ||
typeA: Type<A>, | ||
typeB: Type<B>, | ||
typeC: Type<C>, | ||
typeD: Type<D> | ||
): Type<T> | ||
export function intersection<T extends A & B & C & D & E, A, B, C, D, E>( | ||
typeA: Type<A>, | ||
typeB: Type<B>, | ||
typeC: Type<C>, | ||
typeD: Type<D>, | ||
typeE: Type<E> | ||
): Type<T> | ||
export function intersection<T extends A & B & C & D & E & F, A, B, C, D, E, F>( | ||
typeA: Type<A>, | ||
typeB: Type<B>, | ||
typeC: Type<C>, | ||
typeD: Type<D>, | ||
typeE: Type<E>, | ||
typeF: Type<F> | ||
): Type<T> | ||
export function intersection<T>(...types: Type<unknown>[]): Type<T> { | ||
return new IslyIntersection<T>(...types) | ||
} |
@@ -36,10 +36,5 @@ import type { Flaw } from "./Flaw" | ||
(this.baseType ? `${this.baseType.name} & ` : "") + | ||
JSON.stringify( | ||
globalThis.Object.fromEntries( | ||
globalThis.Object.entries(this.properties).map(([property, type]: [string, Type<any>]) => [ | ||
property, | ||
type.name, | ||
]) | ||
) | ||
) | ||
`{${globalThis.Object.entries(this.properties) | ||
.map(([property, type]: [string, Type<any>]) => `${property}: ${type.name}`) | ||
.join(", ")}}` | ||
) | ||
@@ -46,0 +41,0 @@ } |
{ | ||
"name": "isly", | ||
"version": "0.1.7", | ||
"version": "0.1.8", | ||
"description": "Library for type checking.", | ||
@@ -23,12 +23,12 @@ "author": "Utily Contributors", | ||
"jest": { | ||
"globals": { | ||
"ts-jest": { | ||
"tsconfig": "tsconfig.test.json" | ||
} | ||
}, | ||
"transform": { | ||
"^.+\\.(j|t)sx?$": "ts-jest" | ||
"^.+\\.(j|t)sx?$": [ | ||
"ts-jest", | ||
{ | ||
"tsconfig": "./tsconfig.test.json" | ||
} | ||
] | ||
}, | ||
"transformIgnorePatterns": [ | ||
"<rootDir>/node_modules/(?!(cryptly|authly|isoly|gracely|cloudly-http|cloudly-router|cloudly-formdata)/.*)" | ||
"<rootDir>/node_modules/(?!(cryptly|authly|isoly|isly|gracely|cloudly-http|cloudly-router|cloudly-formdata|cloudly-rest)/.*)" | ||
], | ||
@@ -45,5 +45,3 @@ "testEnvironment": "node", | ||
"!**/dist/**" | ||
], | ||
"preset": "ts-jest", | ||
"testMatch": null | ||
] | ||
}, | ||
@@ -59,14 +57,18 @@ "scripts": { | ||
"devDependencies": { | ||
"@types/jest": "^29.2.5", | ||
"@typescript-eslint/eslint-plugin": "5.48.1", | ||
"@typescript-eslint/parser": "5.48.1", | ||
"eslint": "^8.31.0", | ||
"@types/jest": "^29.5.2", | ||
"@typescript-eslint/eslint-plugin": "5.61.0", | ||
"@typescript-eslint/parser": "5.61.0", | ||
"eslint": "^8.44.0", | ||
"eslint-plugin-prettierx": "github:utily/eslint-plugin-prettierx#utily-20221229", | ||
"eslint-plugin-simple-import-sort": "^8.0.0", | ||
"jest": "^29.3.1", | ||
"eslint-plugin-simple-import-sort": "^10.0.0", | ||
"jest": "^29.6.0", | ||
"prettierx": "github:utily/prettierx#utily-20221229", | ||
"rimraf": "^3.0.2", | ||
"ts-jest": "^29.0.3", | ||
"typescript": "^4.9.4" | ||
"rimraf": "^5.0.1", | ||
"ts-jest": "^29.1.1", | ||
"typescript": "^5.1.6" | ||
}, | ||
"overrides": { | ||
"semver": "^7.5.3", | ||
"optionator": "^0.9.3" | ||
} | ||
} |
@@ -23,3 +23,4 @@ # isly | ||
myArray: string[] | ||
myIntersection: { a: string } & { b: string } | ||
children?: DemoType[] | ||
@@ -48,2 +49,6 @@ | ||
myArray: isly.array(isly.string(), { criteria: "minLength", value: 1 }), | ||
myIntersection: isly.intersection( | ||
isly.object<{ a: string }>({ a: isly.string() }), | ||
isly.object<{ b: string }>({ b: isly.string() }) | ||
), | ||
@@ -135,2 +140,9 @@ // Recursive, optional: | ||
Note, in some circumstances type inference might not always be working the same for | ||
`isly.object({ a: isly.string() }).array()` | ||
and | ||
`isly.array(isly.object({ a: isly.string() }))` | ||
Try the second if the object isn't provided an generic type and the first doesn't work. | ||
### .optional() | ||
@@ -137,0 +149,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
90095
1456
196