gpt4 book ai didi

typescript :如果所有 Prop 都是可选的,有没有办法不需要对象?

转载 作者:搜寻专家 更新时间:2023-10-30 21:33:07 24 4
gpt4 key购买 nike

我正在开发一些将在其他内部项目中使用的库(一种 API 代理)。我想定义方法以便于使用,但我很难使用类型断言:

首先,我有一个用于所有端点方法的工厂:

export type Params<TQueryParams> = {
customConfig?: object;
fullResponse?: boolean;
} & (TQueryParams extends undefined ? { queryParams?: undefined } : { queryParams: TQueryParams })

export const getFactory = <
TQueryParams extends object | undefined = undefined
>({ path }: any) => async (
{ queryParams, customConfig, fullResponse = false }: Params<TQueryParams>
): Promise<any> => {
// some irrelevant factory code
return {};
};

我已经使用了一些魔法,所以根据 TQueryParams 是否需要它,但这还不够。

所以现在当我想定义所有端点并使用工厂时:

// Case 1 - no interface
export const getFile = getFactory({
path: '/api/file'
});

// I'd like for this one to not throw error
getFile();
// These will not throw error - as intended
getFile({});
getFile({
fullResponse: true
});
// This will throw error - as intended
getFile({
queryParams: {}
});
// Case 2 - interface with all optional props
export interface ImageQueryParams {
width?: number;
height?: number;
}

export const getImage = getFactory<ImageQueryParams>({
path: '/api/image'
});

// All of them should be ok, but only last will not throw error
getImage();
getImage({});
getImage({
fullResponse: true
});
getImage({
queryParams: {}
});
// Case 3 - interface with mandatory props
export interface DataQueryParams {
id: number;
sort?: string;
}

export const getData = getFactory<DataQueryParams>({
path: '/api/data'
});

// All will throw error - as intended
getData();
getData({});
getData({
fullResponse: true
});
getData({
queryParams: {}
});
// This one will not throw error - as intended
getData({
queryParams: {
id: 2131241
}
});

只有情况 3 按预期工作。

我特别想实现一个解决方案,如果没有界面或它包含所有可选 Prop ,我将能够不传递任何内容(getImage();)并且没问题。

TS Playground link

最佳答案

我对这些类型定义并不满意(我希望有一些更精简和通用的东西)但它们似乎适用于您的用例:

type CanBeOmitted<T, Y = T, N = never> =
{} extends T ? Y : // T is weak (all props are optional), or
undefined extends T ? Y : // T can be undefined
N;

类型别名 CanBeOmitted<T, Y, N>检查是否 T是全可选对象类型(也称为 "weak type" )或 undefined - 兼容类型。如果是,它返回 Y ;如果不是,则返回 N (默认为 never )。我们可以用它几次来建立你的 Params类型。

这里是:

export type Params<TQueryParams> =
CanBeOmitted<TQueryParams, [undefined?]> |
[
{
customConfig?: object,
fullResponse?: boolean
} & (
{ queryParams: TQueryParams } |
CanBeOmitted<TQueryParams, { queryParams?: never }>
)
];

我做的不同的一件事是使它成为包含参数的元组类型。如果参数可以完全省略,一个optional tuple被退回。

这是 getFactory :

export const getFactory = <
TQueryParams extends object | undefined = undefined
>({ path }: any) => async (
...args: Params<TQueryParams>
): Promise<any> => {
// get rid of conditional types
const arg = args[0] as {
customConfig?: object,
fullResponse?: boolean,
queryParams?: TQueryParams
} | undefined;
const queryParams = arg ? arg.queryParams : undefined;
const customConfig = arg ? arg.customConfig : undefined;
const fullResponse = (arg ? arg.fullResponse : undefined) || false;
// some irrelevant factory code
return {};
};

请注意 Params<TQueryParams>被用作rest tuple而不是作为单个参数。当该元组是可选的时,它允许返回值 getFactory()以零参数调用。另请注意,我们不能再假设该参数存在,因此我们必须更改获取 queryParams 的方式。 , customConfig , 和 fullResponse作为实现中的变量。

好吧,让我们看看它是如何工作的:

// Case 1 - no interface
export const getFile = getFactory({
path: '/api/file'
});

getFile(); // okay
getFile({}); // okay
getFile({
fullResponse: true
}); // okay
getFile({
queryParams: {}
}); // error, {} is not undefined

// Case 2 - interface with all optional props
export interface ImageQueryParams {
width?: number;
height?: number;
}

export const getImage = getFactory<ImageQueryParams>({
path: '/api/image'
});

getImage(); // okay
getImage({}); // okay
getImage({
fullResponse: true
}); // okay
getImage({
queryParams: {}
}); // okay

export interface DataQueryParams {
id: number;
sort?: string;
}

// Case 3 - interface with mandatory props
export const getData = getFactory<DataQueryParams>({
path: '/api/data'
});

getData(); // error, expected 1 arg
getData({}); // error, queryParams missing
getData({
fullResponse: true
}); // error, queryParams missing
getData({
queryParams: {}
}); // error, id missing
getData({
queryParams: {
id: 2131241
}
}); // okay

认为这就是您要找的。好的,希望对你有帮助。祝你好运!

Link to code

关于 typescript :如果所有 Prop 都是可选的,有没有办法不需要对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56518507/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com