Skip to content

Instantly share code, notes, and snippets.

@occar421
Created April 14, 2019 11:34
Show Gist options
  • Save occar421/a17d9f35a52bc7c960738a38b887e0bd to your computer and use it in GitHub Desktop.
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>;`
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