Open JoshuaKGoldberg opened 3 years ago
How about something like this:
interface Template {
inheritance: object;
properties: object;
}
declare class ObjectMakr<T extends Template> {
constructor(template: T);
make<S extends keyof T["properties"]>(pattern: S): Output<T, S>;
}
declare function assert<T>(x: T): void;
const o = new ObjectMakr({
inheritance: {
Solid: {
Block: {},
},
},
properties: {
Block: {photo: 'qmark'},
Solid: {size: 8},
},
} as const);
const b = o.make('Block');
const s = o.make('Solid');
assert<8>(s.size);
assert<'qmark'>(s.photo);
assert<'qmark'>(b.photo);
type Output<T extends Template, S extends keyof T["properties"],
SS = Supers<T, S>,
TT = Transpose<T["properties"]>> = OmitNevers<{
[K in keyof TT]: SS extends keyof TT[K] ? TT[K][SS] : never;
}>;
type Supers<T extends Template, S, Acc = S> =
S extends keyof T["inheritance"] ?
Supers<T, keyof T["inheritance"][S], Acc | keyof T["inheritance"][S]> :
Acc;
type Transpose<T> = {
[J in Inner<T>]: {[K in keyof T]: T[K] extends {[_ in J]: infer U} ? U : never}
};
type Inner<T> = Keys<T[keyof T]>;
type Keys<T> = T extends object ? keyof T : never;
type OmitNevers<T> = Omit<T, Nevers<T>>;
type Nevers<T> = ({[P in keyof T]: T[P] extends never ? P : never })[keyof T];
@shicks I love it, and so soon after TSConf! Very nicely done! 👏
This looks great. If you'd like to send a PR I'd be happy to review it and try it out against what's in this repo. Otherwise no worries, I'll send one soon. Thanks either way!
Overview
Hi everyone from TSConf! 😄
My pinned tweet with slides links
Right now ObjectMakr requires manually defining interfaces alongside its
inheritance
andproperties
map. The actual way it works is slightly less readable from what I put in the slides but generally works the same.I'd really like to not have to write out and update those manual type changes. Now that TypeScript has conditional and recursive types we really should be able to figure this all out in the type system.
As a fun little challenge: make ObjectMakr recognize these types!
Here's a starter snippet working for a simplified version of
inheritance
...Affected Packages
ObjectMakr