diff --git a/README.md b/README.md index e1a718f..63b5bd0 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,14 @@ See: https://github.com/pelotom/type-zoo/pull/14#discussion_r183527882 --- +### `Param#` and `ParamTypes` + +These helpers extract the Parameter-types from Functions. + +See: https://github.com/pelotom/type-zoo/issues/22 + +--- + ### `Pick#` Like `Pick<>` but for `#` of nested levels! diff --git a/types/index.d.ts b/types/index.d.ts index dac85b5..24a1871 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -37,6 +37,45 @@ export type NoInfer = T & { [K in keyof T]: T[K] }; */ export type Purify = { [P in T]: T; }[T]; +/** + * Selects the type of the 0th parameter in a function-type + */ +export type Param0 = Func extends (a: infer T, ...args: any[]) => any + ? T + : never; +/** + * Selects the type of the 1st parameter in a function-type + */ +export type Param1 = Func extends (a: any, b: infer T, ...args: any[]) => any + ? T + : never; +/** + * Selects the type of the 2nd parameter in a function-type + */ +export type Param2 = Func extends (a: any, b: any, c: infer T, ...args: any[]) => any + ? T + : never; +/** + * Selects the type of the 3rd parameter in a function-type + */ +export type Param3 = Func extends (a: any, b: any, c: any, d: infer T, ...args: any[]) => any + ? T + : never; +/** + * Selects the types of all the parameters in a function-type. + * Warnings: + * - This is probably less performant if you're only looking up a single param! {@see Param0-Param# } + * - This omits rest parameters (...args:any[]) + */ +export type ParamTypes = // tslint:disable-line + F extends () => any ? {} : + F extends (p0: infer P0) => any ? [P0] : + F extends (p0: infer P0, p1: infer P1) => any ? [P0, P1] : + F extends (p0: infer P0, p1: infer P1, p2: infer P2) => any ? [P0, P1, P2] : + F extends (p0: infer P0, p1: infer P1, p2: infer P2, p3: infer P3) => any ? [P0, P1, P2, P3] : + // ... -- extend this at your own risk, this could be bad for compilation performance! + never; + /** * Picks 2 levels deep into a nested object! * diff --git a/types/param-n.ts b/types/param-n.ts new file mode 100644 index 0000000..76e9a7f --- /dev/null +++ b/types/param-n.ts @@ -0,0 +1,57 @@ +import { Param0, Param1, Param2, Param3, ParamTypes } from 'type-zoo'; + +function a() { return; } +const b = () => { return; }; + +// $ExpectType {} +type A1 = Param0; +// $ExpectType {} +type B1 = Param0; +// $ExpectType {} +type A2 = ParamTypes; +// $ExpectType {} +type B2 = ParamTypes; + +// $ExpectError +type A3 = A2[0]; +// $ExpectError +type B3 = B2[0]; + +const c1 = (a: string) => { return; }; +const c2 = (a: number, b: boolean) => { return; }; +function c3(a: boolean[], b: object, c: any, d: "foo") { return; } +function c4(a: number, ...args: string[]) { return; } +function c5(a: boolean[], b: object, c: any, d: "foo", e: 1, ...args: any[]) { return; } + +// $ExpectType string +type C1 = Param0; +// $ExpectType {} +type C2 = Param1; +// $ExpectType boolean +type C3 = Param1; +// $ExpectType boolean[] +type C4 = Param0; +// $ExpectType object +type C5 = Param1; +// $ExpectType any +type C6 = Param2; +// $ExpectType "foo" +type C7 = Param3; +// $ExpectType [boolean[], object, any, "foo"] +type C8 = ParamTypes; + +// Var-args -- rest parameters! +// $ExpectType string +type C9 = Param1; +// $ExpectType string +type C10 = Param2; +// $ExpectType string +type C11 = Param3; + +// Currently this type-operator ignores rest parameters (...args:any[]) +// $ExpectType [number] +type C12 = ParamTypes; + +// Currently this type-operator has a max limit of 4 parameter-types unpacked as a tuple +// $ExpectType never +type C13 = ParamTypes; diff --git a/yarn.lock b/yarn.lock index 24b5838..bf46e34 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,8 +3,8 @@ "@types/parsimmon@^1.3.0": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@types/parsimmon/-/parsimmon-1.6.1.tgz#c5d849baf59820389d03564ec4b0bea5900e64cb" + version "1.10.0" + resolved "https://registry.yarnpkg.com/@types/parsimmon/-/parsimmon-1.10.0.tgz#ffb81cb023ff435a41d4710a29ab23c561dc9fdf" ansi-regex@^2.0.0: version "2.1.1" @@ -14,9 +14,9 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -ansi-styles@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" dependencies: color-convert "^1.9.0" @@ -25,8 +25,8 @@ any-promise@^1.0.0, any-promise@^1.3.0: resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" argparse@^1.0.7: - version "1.0.9" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" dependencies: sprintf-js "~1.0.2" @@ -43,8 +43,8 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -64,41 +64,41 @@ chalk@^1.1.3: supports-color "^2.0.0" chalk@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" dependencies: - ansi-styles "^3.1.0" + ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" - supports-color "^4.0.0" + supports-color "^5.3.0" color-convert@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + version "1.9.2" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" dependencies: - color-name "^1.1.1" + color-name "1.1.1" -color-name@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" +color-name@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" commander@^2.12.1: - version "2.13.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" + version "2.16.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50" concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -definitelytyped-header-parser@Microsoft/definitelytyped-header-parser#production: +"definitelytyped-header-parser@github:Microsoft/definitelytyped-header-parser#production": version "0.0.0" - resolved "https://codeload.github.com/Microsoft/definitelytyped-header-parser/tar.gz/f152526f82f51d2baf91a99a397b449342b52db1" + resolved "https://codeload.github.com/Microsoft/definitelytyped-header-parser/tar.gz/a485d0e3f394da4d8628f36bf5b9700102f6b014" dependencies: "@types/parsimmon" "^1.3.0" parsimmon "^1.2.0" diff@^3.2.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" dtslint@^0.3.0: version "0.3.0" @@ -163,9 +163,9 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" inflight@^1.0.4: version "1.0.6" @@ -183,8 +183,8 @@ js-tokens@^3.0.2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" js-yaml@^3.7.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" + version "3.12.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -220,8 +220,8 @@ once@^1.3.0: wrappy "1" parsimmon@^1.2.0: - version "1.6.4" - resolved "https://registry.yarnpkg.com/parsimmon/-/parsimmon-1.6.4.tgz#7ff16d52d58b9769d019b401848ee2c9bd94dd86" + version "1.11.1" + resolved "https://registry.yarnpkg.com/parsimmon/-/parsimmon-1.11.1.tgz#86493d7130636ffdcf748913b84f23916ec16f31" path-is-absolute@^1.0.0: version "1.0.1" @@ -232,8 +232,8 @@ path-parse@^1.0.5: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" resolve@^1.3.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + version "1.8.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" dependencies: path-parse "^1.0.5" @@ -259,11 +259,11 @@ supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" -supports-color@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" +supports-color@^5.3.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" dependencies: - has-flag "^2.0.0" + has-flag "^3.0.0" thenify-all@^1.0.0, thenify-all@^1.6.0: version "1.6.0" @@ -278,12 +278,12 @@ thenify-all@^1.0.0, thenify-all@^1.6.0: any-promise "^1.0.0" tslib@^1.8.0, tslib@^1.8.1: - version "1.9.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" + version "1.9.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" tslint@^5.9.1: - version "5.9.1" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.9.1.tgz#1255f87a3ff57eb0b0e1f0e610a8b4748046c9ae" + version "5.10.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.10.0.tgz#11e26bccb88afa02dd0d9956cae3d4540b5f54c3" dependencies: babel-code-frame "^6.22.0" builtin-modules "^1.1.1" @@ -299,18 +299,18 @@ tslint@^5.9.1: tsutils "^2.12.1" tsutils@^2.12.1: - version "2.19.1" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.19.1.tgz#76d7ebdea9d7a7bf4a05f50ead3701b0168708d7" + version "2.27.2" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.27.2.tgz#60ba88a23d6f785ec4b89c6e8179cac9b431f1c7" dependencies: tslib "^1.8.1" typescript@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.1.tgz#6160e4f8f195d5ba81d4876f9c0cc1fbc0820624" + version "2.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" typescript@next: - version "2.8.0-dev.20180127" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.0-dev.20180127.tgz#289893b34fc86d6ad572b4cbf01e6df815e22fdf" + version "3.0.0-dev.20180710" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.0.0-dev.20180710.tgz#19a5ad2191ddc1f4d5cb29c2f20d37bb98613848" wrappy@1: version "1.0.2"