How to use R.pick with TypeScript
我正在尝试类似
的东西
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import R from 'ramda' import fs from 'fs' import path from 'path' import {promisify} from 'util' const readFile = promisify(fs.readFile) export async function discoverPackageInfo(): Promise<{ name: string, version: string description: string }> { return readFile(path.join(__dirname, '..', 'package.json')) .then(b => b.toString()) .then(JSON.parse) .then(R.pick([ 'name', 'description', 'version', ])) } |
但我得到了
1 2 3 4 5 6 7 8 9 10 11 12 | src/file.ts:13:3 - error TS2322: Type '{ name: string; version: string; description: string; } | Pick' is not assignable to type '{ name: string; version: string; description: string; }'. Type 'Pick' is missing the following properties from type '{ name: string; version: string; description: string; }': name, version, description 13 return readFile(path.join(__dirname, '..', 'package.json')) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14 .then(b => b.toString()) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ... 19 'version', ~~~~~~~~~~~~~~~~ 20 ])) ~~~~~~~ |
我做错了什么?
1 2 3 4 5 | .then(R.pick([ 'name', 'description', 'version' ])) => type Return = Pick // resolves to {}; any stems from JSON.parse type Inner = Exclude<keyof any, Exclude<keyof any,"name" |"description" |"version">> // never |
你想要
1 2 3 4 | readFile(path.join(__dirname,"..","package.json")) .then(b => b.toString()) .then(s => JSON.parse(s) as MyThing) .then(R.pick(["name","description","version"])); |
可以使解析更加类型安全,例如通过使用断言函数/类型保护:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | export async function discoverPackageInfo(): Promise<MyThing> { return readFile(...).then(...) .then(safeParse(assertMyThing)) // <-- change .then(R.pick(...)); } const safeParse = < T >(assertFn: (o: any) => asserts o is T) => (s: string) => { const parsed = JSON.parse(s); assertFn(parsed); return parsed; } function assertMyThing(o: any): asserts o is MyThing { if (!("name" in o) || !("version" in o) || !("description" in o)) throw Error(); } |
Playground(playground 中的外部类型导入可能需要一些时间来加载,否则粘贴到您自己的环境中)