从对象中获取可选的通用值
Get an Optional, Generic, value from an Object
假设我有以下四个对象:
const foo1: Readonly<{foo: number, bar: ?string}> = {
foo: 123
}
const foo1: Readonly<{foo: number, bar: ?string}> = {
foo: 123,
bar: '1123'
}
const bar1: Readonly<{foo2: number, bar2: ?string}> = {
foo2: 123
}
const foo1: Readonly<{foo: number, bar: ?string}> = {
foo2: 123,
bar2: '1123'
}
我现在想将它们转换成 fp-ts Option
形式的承载对象:
{foo: number, bar: Option<string>}
天真的方法是编写两个函数(或者确实内联进行这些计算):
const makeOptional1 = (obj: Readonly<{foo: number, bar: ?string}>) => {
return (obj.bar === undefined) ? none : some(obj[key]
}
const makeOptional2 = (obj: Readonly<{foo2: number, bar2: ?string}>) => {
return (obj.bar2 === undefined) ? none : some(obj[key]
}
但是说,我想提取一个更抽象的函数,一个可以接受任意对象和任意键的函数,以及 return 正确的选项。
第一次尝试可能看起来像这样:
const optionalKey = <T, D>(val: D, key: string): Option<T> => {
if (val[key] === undefined) {
return none
} else {
return some(val[key])
}
}
编译失败:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'unknown'.
No index signature with a parameter of type 'string' was found on type 'unknown'.ts(7053)
错误消息非常有道理,但我不知道如何修复它。欢迎任何想法
请看:
TS playground
import { Option, some, none } from 'fp-ts/lib/Option';
const foo1: Readonly<{ foo: number, bar?: string }> = {
foo: 123
}
const foo2: Readonly<{ foo: number, bar?: string }> = {
foo: 123,
bar: '1123'
}
const bar1: Readonly<{ foo2: number, bar2?: string }> = {
foo2: 123
}
const bar2: Readonly<{ foo2: number, bar2?: string }> = {
foo2: 123,
bar2: '1123'
}
const makeOptional1 = <T extends Readonly<{ foo: number, bar?: string }>, K extends keyof T>(obj: T, key: K) => {
return (obj.bar === undefined) ? none : some(obj[key])
}
const makeOptional2 = <T extends Readonly<{ foo2: number, bar2?: string }>, K extends keyof T>(obj: T, key: K) => {
return (obj.bar2 === undefined) ? none : some(obj[key])
}
type Values<T> = T[keyof T];
const optionalKey = <T, K extends keyof T>(val: T, key: K): Option<Values<T>> => val[key] ? some(val[key]) : none;
const result = optionalKey({ age: 1 }, 'age'); // Option<number>
fp-ts version:2.8.6
假设我有以下四个对象:
const foo1: Readonly<{foo: number, bar: ?string}> = {
foo: 123
}
const foo1: Readonly<{foo: number, bar: ?string}> = {
foo: 123,
bar: '1123'
}
const bar1: Readonly<{foo2: number, bar2: ?string}> = {
foo2: 123
}
const foo1: Readonly<{foo: number, bar: ?string}> = {
foo2: 123,
bar2: '1123'
}
我现在想将它们转换成 fp-ts Option
形式的承载对象:
{foo: number, bar: Option<string>}
天真的方法是编写两个函数(或者确实内联进行这些计算):
const makeOptional1 = (obj: Readonly<{foo: number, bar: ?string}>) => {
return (obj.bar === undefined) ? none : some(obj[key]
}
const makeOptional2 = (obj: Readonly<{foo2: number, bar2: ?string}>) => {
return (obj.bar2 === undefined) ? none : some(obj[key]
}
但是说,我想提取一个更抽象的函数,一个可以接受任意对象和任意键的函数,以及 return 正确的选项。
第一次尝试可能看起来像这样:
const optionalKey = <T, D>(val: D, key: string): Option<T> => {
if (val[key] === undefined) {
return none
} else {
return some(val[key])
}
}
编译失败:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'unknown'.
No index signature with a parameter of type 'string' was found on type 'unknown'.ts(7053)
错误消息非常有道理,但我不知道如何修复它。欢迎任何想法
请看: TS playground
import { Option, some, none } from 'fp-ts/lib/Option';
const foo1: Readonly<{ foo: number, bar?: string }> = {
foo: 123
}
const foo2: Readonly<{ foo: number, bar?: string }> = {
foo: 123,
bar: '1123'
}
const bar1: Readonly<{ foo2: number, bar2?: string }> = {
foo2: 123
}
const bar2: Readonly<{ foo2: number, bar2?: string }> = {
foo2: 123,
bar2: '1123'
}
const makeOptional1 = <T extends Readonly<{ foo: number, bar?: string }>, K extends keyof T>(obj: T, key: K) => {
return (obj.bar === undefined) ? none : some(obj[key])
}
const makeOptional2 = <T extends Readonly<{ foo2: number, bar2?: string }>, K extends keyof T>(obj: T, key: K) => {
return (obj.bar2 === undefined) ? none : some(obj[key])
}
type Values<T> = T[keyof T];
const optionalKey = <T, K extends keyof T>(val: T, key: K): Option<Values<T>> => val[key] ? some(val[key]) : none;
const result = optionalKey({ age: 1 }, 'age'); // Option<number>
fp-ts version:2.8.6