如何将R.pick与TypeScript一起使用

如何将R.pick与TypeScript一起使用,typescript,ramda.js,Typescript,Ramda.js,我在尝试类似的东西 从“ramda”导入R 从“fs”导入fs 从“路径”导入路径 从“util”导入{promisify} const readFile=promisify(fs.readFile) 导出异步函数discoverPackageInfo():Promise{ 返回readFile(path.join(uuu dirname,“…”,“package.json')) .然后(b=>b.toString()) .then(JSON.parse) .然后(右)选择([ “姓名”, “说

我在尝试类似的东西

从“ramda”导入R
从“fs”导入fs
从“路径”导入路径
从“util”导入{promisify}
const readFile=promisify(fs.readFile)
导出异步函数discoverPackageInfo():Promise{
返回readFile(path.join(uuu dirname,“…”,“package.json'))
.然后(b=>b.toString())
.then(JSON.parse)
.然后(右)选择([
“姓名”,
“说明”,
“版本”,
]))
}
但是我有

src/file.ts:13:3 - error TS2322: Type '{ name: string; version: string; description: string; } | Pick<any, never>' is not assignable to type '{ name: string; version: string; description: string; }'.
  Type 'Pick<any, never>' 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     ]))
    ~~~~~~~

src/file.ts:13:3-错误TS2322:类型“{name:string;version:string;description:string;}| Pick”不能分配给类型“{name:string;version:string;description:string;}”。
类型“Pick”缺少类型“{name:string;version:string;description:string;}”中的以下属性:名称、版本、说明
13返回readFile(path.join(uuu dirname,“…”,“package.json'))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14.然后(b=>b.toString())
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
... 
19“版本”,
~~~~~~~~~~~~~~~~
20     ]))
~~~~~~~
我做错了什么?

JSON.parse
。解析后的返回类型如下:

.then(R.pick([ 'name', 'description', 'version' ])) 
=>
type Return = Pick<any, Inner> // resolves to {}; any stems from JSON.parse
type Inner = Exclude<keyof any,
    Exclude<keyof any, "name" | "description" | "version">> // never
,例如,通过使用/类型防护装置:

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();
}
导出异步函数discoverPackageInfo():Promise{ 返回readFile(…)。然后(…) .then(safeParse(assertMyThing))//断言o是T=>(s:string)=>{ const parsed=JSON.parse; 资产fn(已解析); 返回解析; } 函数断言虚构(o:any):断言o是虚构的{ if(!(“o中的名称”)o!(“o中的版本”)o!(“o中的说明”) 抛出错误(); }
(操场中的外部类型导入可能需要一些时间才能加载,否则将粘贴到您自己的环境中)

是的,我知道使用
async
。那么
就不太合适了。
async
在这里实际上是不必要的。没有正确的代码就可以工作。但是,我正在构建我的代码,使其在非CPU的任何东西上都具有async,只是为了迫使人们正确思考问题。最终成为一个结构和注释方面的练习n、 我发现它对我很有帮助。非常有帮助,谢谢!有没有更标准/打包的方法来实现这一点?比如,从类型定义生成断言函数?我还没有看过手册(我只是通过练习学习)我很感谢任何指点!我不确定断言函数的生成器。但是有很多自动生成类型的guard库,我个人觉得很吸引人!而且似乎得到了积极的维护和支持。你也可以看看起点。顺便说一句:如果你想使用断言函数,那么基于生成的类型保护,转换应该没有问题,例如。作为参考,我最终得出以下结论:
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();
}