某些Web服务根据请求的属性提供东西。我想创建一个带有属性的函数,在内部调用Web服务并返回请求的数据。
使用数据的函数现在应该知道特定的键现在不是未定义的。
当我自己寻找解决方案时,我发现了一些可能有用的东西,但无法从中创建有用的东西:
还有一个额外的麻烦:在这种情况下,总是有默认属性,例如id。
interface Something {
id: string;
foo?: string;
bar?: number;
}
// use 'keyof Something' in some ways here?
type OptionalProp = 'foo' | 'bar'
type SomethingSpecific<K extends keyof Something> = {
[k in K]: NonNullable<Something[k]>
};
function get(properties: OptionalProp[]): Something {
const result: Something = {
id: '1337'
};
if (properties.includes('foo')) {
result.foo = 'bar';
}
if (properties.includes('bar')) {
result.bar = 42;
}
return result;
}
console.log(usage());
function usage(): number {
const result = get(['bar']);
return result.bar * 1;
}
答案 0 :(得分:1)
因此,可以使用Can I Use来确定类型的哪些键是可选的,并且您还可以为get()
函数提供一个调用签名,该函数承诺返回一个带有某些内容的Something
现在需要使用以前可选的属性(最好将其设为一个a way的函数,以使实现签名可以像以前一样松散;否则,在实现中会引起很多抱怨) 。还要注意,标准库中有一个名为overload的类型别名,该别名采用对象类型T
并返回新类型,其中现在需要所有可选属性。将Required<T>
和Pick<T, K>
和Required<T>
结合使用应该可以:
interface Something {
id: string;
foo?: string;
bar?: number;
}
// get the optional keys of an object type
type OptionalKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? K : never }[keyof T];
type OptionalProp = OptionalKeys<Something>
// make get() a generic function that returns an intersection of Something with
// a Required<Pick<Something, K>> for the passed-in K parameters
function get<K extends OptionalProp>(
properties: K[]
): Required<Pick<Something, K>> & Something;
function get(properties: OptionalProp[]): Something {
// impl here
return null!
}
const result = get(['bar']);
// const result: Required<Pick<Something, "bar">> & Something
result.bar * 1; // okay now
这应该为您工作。请注意,返回的get()
类型将是像Required<Pick<Something, "bar">> & Something
这样的交集类型。如果您想要一种更直接的属性包对象类型,则可以将get()
签名更改为对实现者来说较难看但对调用者来说更好:
function get<K extends OptionalProp,
R extends Something=Required<Pick<Something, K>> & Something
>(properties: K[]): { [P in keyof R]: R[P] };
function get(properties: OptionalProp[]): Something { /* impl */ }
// impl here
return null!
}
const result = get(['bar']);
//const result: {
// bar: number;
// id: string;
// foo?: string | undefined;
//}
好的,希望能有所帮助。祝你好运!