Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@marcj
Last active February 17, 2019 17:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcj/266394179d50dad98d7fe15ae93ae488 to your computer and use it in GitHub Desktop.
Save marcj/266394179d50dad98d7fe15ae93ae488 to your computer and use it in GitHub Desktop.
Typescript creating a new deep subtype based on runtime arguments.
interface Writer {
id: number;
username: string;
notIncludedAsWell: string;
}
interface Post {
id: number;
content: string;
notIncluded: string;
writer: Writer
}
type Primitive = string | boolean | number | symbol;
type ValuesOf<T extends Primitive[]> = T[number];
type PropertyNames<T> = { [K in keyof T]: T[K] extends Primitive ? K : never }[keyof T];
type PickByArray<T, KW extends K[], K extends keyof T = any> = {
[P in ValuesOf<KW>]: T[P]
}
function Bla2<
ValidRootTypes extends keyof Post,
SecondLevelProperties extends {[PT in keyof Post]?: PropertyNames<Post[PT]>[]},
SecondLevelProperties2 extends keyof SecondLevelProperties & keyof Post,
R = Pick<Post, ValidRootTypes> & {[PT in SecondLevelProperties2]: PickByArray<Post[PT], SecondLevelProperties[PT]>}
>(rootPropertyNames: ValidRootTypes[], secondLevelProperties: SecondLevelProperties): R {
return {} as R;
}
//this is what we expect
type expect = Pick<Post, 'id' | 'content'> & {writer: Pick<Post['writer'], 'id' | 'username'>};
//this is what we actually get
const actual = Bla2(['id', 'content'], {writer: ['id', 'username']});
actual.id; //number
actual.
@namse
Copy link

namse commented Feb 17, 2019

line 24 : ValidRootTypes extends PropertyNames<Post>,, To avoid input writer in root property names

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment