TypeScript:如何为函数中的任何键键入对象剩余分布
Posted
技术标签:
【中文标题】TypeScript:如何为函数中的任何键键入对象剩余分布【英文标题】:TypeScript: How to type object rest spread for any keys in function 【发布时间】:2021-05-17 05:16:03 【问题描述】:我有一个函数,它接受一个对象并返回一个对象。它返回整个传入对象,但添加了一个键。对象的形状是未知的,所以它可以有任何键,但它必须有 2 个特定的键。
const myFunction = (
num1,
num2,
...rest
:
num1: number;
num2: number;
) => (
num1,
num2,
sum: num1 + num2,
...rest,
);
myFunction( num1: 4, num2: 3, foo: 'bar' );
// or myFunction( num1: 4, num2: 3, baz: 'qux', quux: 'quuz' );
TypeScript 在这里大喊foo
。
Argument of type ' num1: number; num2: number; foo: string; ' is not assignable to parameter of type ' num1: number; num2: number; '.
Object literal may only specify known properties, and 'foo' does not exist in type ' num1: number; num2: number;
这是一个简化的例子。
这是我的实际功能以及我如何尝试使用 extends
解决它。
import type NextApiRequest, NextApiResponse from 'next';
import getSession from 'utils/sessions';
const withAuthentication = async <
T extends
request: NextApiRequest;
response: NextApiResponse;
,
K extends T
>(
request,
response,
...rest
: T): Promise<
userSession:
issuer: string;
publicAddress: string;
email: string;
;
& K
> =>
const userSession = await getSession(request);
return request, response, userSession, ...rest ;
;
export default withAuthentication;
实际的错误是这样的。
Type ' request: NextApiRequest; response: NextApiResponse<any>; userSession: any; & Omit<T, "request" | "response">' is not assignable to type ' userSession: issuer: string; publicAddress: string; email: string; ; & K'.
Type ' request: NextApiRequest; response: NextApiResponse<any>; userSession: any; & Omit<T, "request" | "response">' is not assignable to type 'K'.
' request: NextApiRequest; response: NextApiResponse<any>; userSession: any; & Omit<T, "request" | "response">' is assignable to the constraint of type 'K', but 'K' could be instantiated with a different subtype of constraint ' request: NextApiRequest; response: NextApiResponse<any>; '.
你怎么能键入这样的函数?
【问题讨论】:
不确定这是否是个好主意; num1: number; num2: number; & any
作为参数类型。
【参考方案1】:
使用 rest 参数进行解构使得它难以进行类型检查,但如果您只是扩展参数对象并添加 userSession
属性,您最终会得到一个相当易读的解决方案:
const withAuthentication = async <
T extends
request: NextApiRequest;
response: NextApiResponse;
>(arg: T): Promise<
userSession:
issuer: string;
publicAddress: string;
email: string;
;
& T> =>
const userSession = await getSession(arg.request);
return ...arg, userSession ;
;
(TypeScript playground)
【讨论】:
【参考方案2】:这段代码也可以编译,但我不知道它是否是最好的方法。
import UserSession from 'features/user-authentication/types';
import type NextApiRequest, NextApiResponse from 'next';
import getSession from 'utils/sessions';
const withAuthentication = async <
T extends
request: NextApiRequest;
response: NextApiResponse;
>(
request,
response,
...rest
: T): Promise<
request: NextApiRequest;
response: NextApiResponse;
userSession: UserSession;
& Omit<T, 'request' | 'response'>
> =>
const userSession = await getSession(request);
if (userSession)
return request, response, userSession, ...rest ;
throw new Error('Unauthenticated');
;
export default withAuthentication;
【讨论】:
【参考方案3】:您可以使用generics。
演示:https://repl.it/@chvolkmann/InternalFrugalCopyleft
interface MyArgs
a: number
b: number
const doSomething = <A extends MyArgs>(args: A) => (
...args,
sum: args.a + args.b
)
console.log(doSomething( a: 10, b: 5, foo: 'bar' ))
// Output:
// a: 10, b: 5, foo: 'bar', sum: 15
【讨论】:
以上是关于TypeScript:如何为函数中的任何键键入对象剩余分布的主要内容,如果未能解决你的问题,请参考以下文章
使用随机数组字符串键入对象键/属性 - TypeScript