[英]Object with conditionally optional keys
function getColors(
url: string,
config: Config
): Promise<Result>;
}
type Config = {
dominant?: boolean;
average?: boolean;
};
type Result = {
dominant?: string;
average?: string;
};
How can I say if dominant
was passed as true
to the config object eg getColors(url, { dominant: true})
then it is not optional in Result
.我怎么能说如果
dominant
被作为true
传递给配置对象,例如getColors(url, { dominant: true})
那么它在Result
不是可选的。
async () => {
let example : string;
const colors = await getColors(url, {dominant: true});
example = colors.dominant;
// ^^^^^^ Type 'string | undefined' is not assignable to type 'string'.
// Type 'undefined' is not assignable to type 'string'
};
We can do that by conditional types .我们可以通过条件类型来做到这一点。 Consider:
考虑:
type Config = {
dominant?: boolean;
average?: boolean;
};
type Result = {
dominant?: string;
average?: string;
};
declare function getColors<C extends Config>(
url: string,
config: C
): Promise<Result & (C['dominant'] extends true ? {dominant: string} : {})>;
async function f() {
const colors = await getColors('url', { dominant: true })
colors.dominant // is non-optional string
}
The core thing is to have Config
as generic in getColors
and append conditional behavior in the return type: Result & (C['dominant'] extends true ? {dominant: string} : {})
.核心是让
Config
在getColors
通用,并在返回类型中附加条件行为: Result & (C['dominant'] extends true ? {dominant: string} : {})
。 What we do here is - if dominant
is true in config, we intersect with our type object having dominant
required, if dominant
is false we intersect with {}
which is neutral element, so we get Result
back.我们在这里做的是 - 如果在配置中
dominant
为真,我们与我们的类型对象相交具有dominant
需要,如果dominant
为假,我们与{}
相交,这是中性元素,所以我们得到Result
。
You can provide two signatures by overloading the function:您可以通过重载函数来提供两个签名:
interface Config { average?: boolean, dominant?: boolean }
interface ConfigDominant extends Config { dominant: true }
interface Result { average?: string, dominant?: string }
interface ResultDominant extends Result { dominant: string }
// more specific signature must go first
function getColors(url: string, config: ConfigDominant): Promise<ResultDominant>;
// less specific signature
function getColors(url: string, config: Config): Promise<Result>;
// implementation
function getColors(url: string, config: Config): Promise<Result> {
throw new Error('not implemented');
}
async (url: string) => {
const colors = await getColors(url, {dominant: true});
// no error here
let example: string = colors.dominant;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.