Created
April 14, 2019 11:34
-
-
Save occar421/a17d9f35a52bc7c960738a38b887e0bd to your computer and use it in GitHub Desktop.
typing for "brother" field in TypeScript (just a scribble); union-type for each permutation for subsets of object properties in tuple `SubsAlpha` & `type TupleAtMost3<T> = [] | SubsAlpha<T>;`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { AssertTrue, Has, IsExact } from "conditional-type-checks"; | |
// interface A<T1 extends { [key: string]: any }, T2 extends T1> { | |
// a: T1; | |
// // b: (keyof T2)[]; // 現実解 | |
// b: Workaround<keyof T2>[]; // 現実解 | |
// // b: TupleAtMost3<T2>; // 重複を防ぐようにするにはすべての組み合わせを列挙する? | |
// } | |
// interface A<T1 extends { [key: string]: any }, T2 extends T1> { | |
interface A<T extends { [key: string]: any }, Keys extends (keyof T)[]> { | |
a: T; | |
// b: (keyof T2)[]; // 現実解 | |
// b: Workaround<keyof T2>[]; // 現実解 | |
b: Keys; // 現実解 | |
} | |
// type Workaround<K> = K[] & { length: 1 }; | |
// declare function f<T1 extends { [key: string]: any }, T2 extends T1>( | |
declare function f<T extends { [key: string]: any }, Keys extends (keyof T)[]>( | |
obj: A<T, Keys> | |
): A<T, Keys>; | |
const a = f({ a: { c: 1, d: 2 }, b: ["c", "d"] }); | |
const b = f({ a: { c: 1, d: 2 }, b: ["x"] }); | |
const c = f({ a: { x: 1 }, b: ["x"] }); | |
const d = f({ a: { x: 1 }, b: ["x", "x"] }); | |
const e = f({ a: { x: 1, y: 2 }, b: ["x", "y"] }); | |
const g = f({ a: { x: 1, y: 2 }, b: ["x", "y", "z"] }); | |
const h = f({ a: { x: 1, y: 2 }, b: ["x"] }); | |
const i = f({ a: { x: 1, y: 2 }, b: ["x", "x"] }); | |
const j = f({ a: { x: 1, y: 2, z: 3 }, b: ["x"] }); | |
interface V<MInput extends any, MOutput extends MInput> { | |
data(): MInput extends any ? MInput : never; | |
methods: { [key: string]: (this: { readonly $state: MOutput }) => void }; | |
} | |
declare function v<M1 extends any, M2 extends M1>(obj: V<M1, M2>): V<M1, M2>; | |
const component = v({ | |
data() { | |
return { a: 1 }; | |
}, | |
methods: { | |
a() { | |
this.$state; | |
} | |
} | |
}); | |
type C<First, Rest> = [First, ...Rest[]]; | |
const cc: C<string, number> = ["1", 1, 2]; | |
declare const ddd: keyof typeof cc; | |
declare const eee: keyof []; | |
// [] | ["0"] | ["0", "1"] | ["1", "0"] | |
// type CCC = [] | [...("0" | "1")[]]; | |
type DDD<T extends [...string[]]> = T extends { length: 0 } | |
? [] | |
: T extends { length: 1 } | |
? [] | ["0"] | |
: T extends { length: 2 } | |
? [] | ["0"] | ["1"] | ["0", "1"] | ["1", "0"] | |
: never; | |
namespace TypeChecks { | |
type doTest0 = AssertTrue<IsExact<DDD<[]>, []>>; | |
type doTest1 = AssertTrue<Has<DDD<["a"]>, ["0"]>>; | |
} | |
// type Hoge<Union> = Union extends infer T1 | infer T2 ? T1 : never; | |
// type TupleAtMost2< | |
// Union | |
// > = /*Union[] extends (infer T1 | infer T2 | infer T3)[] | |
// ? [T1, T2, T3] | |
// :*/ Union[] extends ( | |
// | infer T1 | |
// | infer T2)[] | |
// ? [T1, T2] | |
// : Union extends infer T | |
// ? [T] | |
// : never; | |
type TupleAtMost2< | |
Union | |
> = /*Union[] extends (infer T1 | infer T2 | infer T3)[] | |
? [T1, T2, T3] | |
:*/ Union[] extends ( | |
| infer T1 | |
| infer T2)[] | |
? [T1, T2] | |
: Union extends infer T | |
? [T] | |
: never; | |
type AAAAA<T, K extends keyof T> = K extends keyof T ? [Pick<T, K>] : never; | |
type BBBBB<T, K extends keyof T> = K extends keyof T ? never : never; | |
type KnownKeys<T> = { | |
[K in keyof T]: string extends K ? never : number extends K ? never : K | |
} extends { [_ in keyof T]: infer U } | |
? ({} extends U ? never : U) | |
: never; | |
// union distribution + not distributed | |
// type TupleAtMost2<U> = Sub<U>; | |
type Sub1<T, K extends keyof T = keyof T> = K extends keyof T | |
? Pick<T, Exclude<keyof T, K>> | |
: never; | |
type Subs< | |
T, | |
K1 extends keyof T = keyof T, | |
K2 extends keyof T = keyof T, | |
K3 extends keyof T = keyof T, | |
K4 extends keyof T = keyof T, | |
K5 extends keyof T = keyof T, | |
K6 extends keyof T = keyof T, | |
K7 extends keyof T = keyof T, | |
K8 extends keyof T = keyof T | |
> = K1 extends keyof T | |
? K2 extends keyof T | |
? K3 extends keyof T | |
? K4 extends keyof T | |
? K5 extends keyof T | |
? K6 extends keyof T | |
? K7 extends keyof T | |
? K8 extends keyof T | |
? Pick< | |
T, | |
Exclude<keyof T, K1 | K2 | K3 | K4 | K5 | K6 | K7 | K8> | |
> | |
: never | |
: never | |
: never | |
: never | |
: never | |
: never | |
: never | |
: never; | |
namespace TypeChecks { | |
type doTest0 = AssertTrue<IsExact<DDD<[]>, []>>; | |
type doTest1 = AssertTrue<Has<DDD<["a"]>, ["0"]>>; | |
} | |
// type AtLeastOne<T> = Spread<T, keyof T>; | |
// type Spread<T, K extends keyof T> = K extends keyof T | |
// ? PartiallyPartial<T, Exclude<keyof T, K>> | |
// : never; | |
// type PartiallyPartial<T, K extends keyof T> = Partial<Pick<T, K>> & | |
// Pick<T, Exclude<keyof T, K>>; | |
// negate type? | |
// type A<Union> = { 0: Union[0], 1: Union[1] } | |
// type Target = { a: number; b: number; c: number; d: number }; | |
type Target = { a: number; b: number; c: number }; | |
type Middle = Subs<Target> | Target; | |
const m: Middle = {}; | |
type SubsAlpha< | |
T, | |
K1 extends keyof T = keyof T, | |
K2 extends keyof T = keyof T, | |
K3 extends keyof T = keyof T | |
> = K1 extends keyof T | |
? K2 extends keyof T | |
? K3 extends keyof T | |
? (K1 extends K2 | |
? (/* K1 == K2, then */ K2 extends K3 | |
? /* K1 == K2 == K3, so */ [K1] | |
: /* K1 == K2 != K3, so */ [K1, K3]) | |
: /* K1 != K2, then */ K2 extends K3 | |
? never | |
: /* K1 != K2 && K2 != K3, then */ K3 extends K1 | |
? never | |
: /* K1,K2,K3 are distinguish, so */ [K1, K2, K3]) | |
: never | |
: never | |
: never; | |
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; | |
type SubsBeta< | |
T, | |
Keys extends any[] = [], | |
NewKey extends keyof T = keyof T | |
> = Exclude<T, Keys[number]> extends never | |
? never | |
: NewKey extends keyof T | |
? { 1: NewKey; 0: SubsBeta<Omit<T, NewKey>, [NewKey]> } | |
: never; | |
// type SubBeta_<T, Keys extends any[] = [], NewKey extends keyof T = keyof T> = SubsAlpha<T, NewKey>; | |
type MiddleAlpha = [] | SubsAlpha<Target>; | |
type MiddleBeta = [] | SubsBeta<Target>; | |
type TupleAtMost3<T> = [] | SubsAlpha<T>; | |
const wewrq: { "0": 1 } = [1]; | |
type UnionToTuple<U> = UnionToTupleRecursively<[], U>; | |
type UnionToTupleRecursively<T extends any[], U> = { | |
1: T; | |
0: Math; | |
}[[U] extends [never] ? 1 : 0]; | |
type ASSS = UnionToTuple<"a" | "b">; | |
type Values<T> = T extends { [index: number]: infer E } ? E : never; | |
const aaa = ["a", "b"] as const; | |
type As = Values<typeof aaa>; | |
// type A2<T1 extends { [key: T2[number]]: any }, T2 extends string[]> = T2 extends (infer T3)[] ? { | |
// a: T1; | |
// b: T3; | |
// } : never; | |
// | |
// declare function f2<T1 extends { [key: string]: any }, T2>( | |
// obj: A2<T1, T2> | |
// ): A2<T1, T2>; | |
// | |
// const a2 = f2({ a: { c: 1, d: 2 }, b: ["c", "d"] as const }); | |
// const b2 = f2({ a: { c: 1, d: 2 }, b: ["x"] as const }); | |
// const c2 = f2({ a: { x: 1 }, b: ["x"] }); | |
// const d2 = f2({ a: { x: 1 }, b: ["x", "x"] }); | |
// const e2 = f2({ a: { x: 1, y: 2 }, b: ["x", "y"] }); | |
// const g2 = f2({ a: { x: 1, y: 2 }, b: ["x", "y", "z"] }); | |
// const h2 = f2({ a: { x: 1, y: 2 }, b: ["x"] }); | |
// const i2 = f2({ a: { x: 1, y: 2 }, b: ["x", "x"] }); | |
// const j2 = f2({ a: { x: 1, y: 2, z: 3 }, b: ["x"] }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment