TS - 类型 - 在保留类型的同时省略函数中参数对象中的字段
TS - types - omit field in parameter object in function while keeping types
我有一个类型可以省略函数参数对象中的指定字段,如下所示:
type OmitFields<F, K extends string> = F extends (props: infer P) => infer R ? (props: Omit<P, K>) => R : never;
并像这样使用它:
type Omitted = OmitFields<typeof functionWithObjectParam, 'first' | 'second'>
如何让类型参数 K 知道 props 对象被推断为的类型,并将正确的字符串限制为其键?
我想你想要这样的东西:
type OmitFields<
F extends (props: any) => any,
K extends keyof Parameters<F>[0],
> = (props: Omit<Parameters<F>[0], K>) => ReturnType<F>
这里 F
被限制为一个接受一个参数的函数。 K
受限于该参数的键。
然后你就可以重建函数类型而不需要任何花哨的东西infer
。
这似乎是你想要的:
function functionWithObjectParam(props: { a: number, b: number }) {}
type Omitted = OmitFields<typeof functionWithObjectParam, 'b'> // ok
type OmittedBad = OmitFields<typeof functionWithObjectParam, 'bad'> // Type '"bad"' does not satisfy the constraint '"b" | "a"'.(2344)
declare const fn: Omitted
fn({ a: 1 }) // ok
fn({ a: 1, b: 2 })
// Argument of type '{ a: number; b: number; }' is not assignable to parameter of type 'Omit<{ a: number; b: number; }, "b">'.
// Object literal may only specify known properties, and 'b' does not exist in type 'Omit<{ a: number; b: number; }, "b">'.
您可以使用 TypeScript 实用程序类型 Parameters
而不是推断 F 函数第一个参数的类型 (props
)。
Constructs a tuple type from the types used in the parameters of a function type Type
.
从那里,您可以直接更具体地约束您的 K
泛型,而不仅仅是 extends string
:例如 K extends keyof Parameters<F>[0]
现在为了更接近你的例子,我们可以让 F 可以是函数以外的东西,在这种情况下条件稍微复杂一些,但仍然 do-able:
type OmitFields<
F,
K extends (
F extends (...args: any) => any
? keyof Parameters<F>[0]
: string
)
> = F extends (...args: any) => infer R
? (props: Omit<Parameters<F>[0], K>) => R
: never;
declare function functionWithObjectParam(props: { key1: number; second: boolean; }): string;
type Omitted = OmitFields<typeof functionWithObjectParam, 'first' | 'second'>
// TS2344 Type '"first" | "second"' does not satisfy the constraint '"second" | "key1"'. Type '"first"' is not assignable to type '"second" | "key1"'.
type Omitted2 = OmitFields<typeof functionWithObjectParam, 'key1' | 'second'> // Okay
type Omitted3 = OmitFields<string, 'first' | 'second'> // Okay
但是我怀疑在你的情况下条件类型只是为了启用类型推断。如果你有一个只接受函数的类型,它就会变得简单得多:
type OmitFields2<
F extends (...args: any) => any,
K extends keyof Parameters<F>[0]
> = (props: Omit<Parameters<F>[0], K>) => ReturnType<F>
type Omitted4 = OmitFields2<typeof functionWithObjectParam, 'first' | 'second'>
// TS2344 Type '"first" | "second"' does not satisfy the constraint '"second" | "key1"'.
type Omitted5 = OmitFields2<typeof functionWithObjectParam, 'key1' | 'second'> // Okay
type Omitted6 = OmitFields2<string, 'first' | 'second'>
// TS2344 Type 'string' does not satisfy the constraint '(...args: any) => any'.
我有一个类型可以省略函数参数对象中的指定字段,如下所示:
type OmitFields<F, K extends string> = F extends (props: infer P) => infer R ? (props: Omit<P, K>) => R : never;
并像这样使用它:
type Omitted = OmitFields<typeof functionWithObjectParam, 'first' | 'second'>
如何让类型参数 K 知道 props 对象被推断为的类型,并将正确的字符串限制为其键?
我想你想要这样的东西:
type OmitFields<
F extends (props: any) => any,
K extends keyof Parameters<F>[0],
> = (props: Omit<Parameters<F>[0], K>) => ReturnType<F>
这里 F
被限制为一个接受一个参数的函数。 K
受限于该参数的键。
然后你就可以重建函数类型而不需要任何花哨的东西infer
。
这似乎是你想要的:
function functionWithObjectParam(props: { a: number, b: number }) {}
type Omitted = OmitFields<typeof functionWithObjectParam, 'b'> // ok
type OmittedBad = OmitFields<typeof functionWithObjectParam, 'bad'> // Type '"bad"' does not satisfy the constraint '"b" | "a"'.(2344)
declare const fn: Omitted
fn({ a: 1 }) // ok
fn({ a: 1, b: 2 })
// Argument of type '{ a: number; b: number; }' is not assignable to parameter of type 'Omit<{ a: number; b: number; }, "b">'.
// Object literal may only specify known properties, and 'b' does not exist in type 'Omit<{ a: number; b: number; }, "b">'.
您可以使用 TypeScript 实用程序类型 Parameters
而不是推断 F 函数第一个参数的类型 (props
)。
Constructs a tuple type from the types used in the parameters of a function type
Type
.
从那里,您可以直接更具体地约束您的 K
泛型,而不仅仅是 extends string
:例如 K extends keyof Parameters<F>[0]
现在为了更接近你的例子,我们可以让 F 可以是函数以外的东西,在这种情况下条件稍微复杂一些,但仍然 do-able:
type OmitFields<
F,
K extends (
F extends (...args: any) => any
? keyof Parameters<F>[0]
: string
)
> = F extends (...args: any) => infer R
? (props: Omit<Parameters<F>[0], K>) => R
: never;
declare function functionWithObjectParam(props: { key1: number; second: boolean; }): string;
type Omitted = OmitFields<typeof functionWithObjectParam, 'first' | 'second'>
// TS2344 Type '"first" | "second"' does not satisfy the constraint '"second" | "key1"'. Type '"first"' is not assignable to type '"second" | "key1"'.
type Omitted2 = OmitFields<typeof functionWithObjectParam, 'key1' | 'second'> // Okay
type Omitted3 = OmitFields<string, 'first' | 'second'> // Okay
但是我怀疑在你的情况下条件类型只是为了启用类型推断。如果你有一个只接受函数的类型,它就会变得简单得多:
type OmitFields2<
F extends (...args: any) => any,
K extends keyof Parameters<F>[0]
> = (props: Omit<Parameters<F>[0], K>) => ReturnType<F>
type Omitted4 = OmitFields2<typeof functionWithObjectParam, 'first' | 'second'>
// TS2344 Type '"first" | "second"' does not satisfy the constraint '"second" | "key1"'.
type Omitted5 = OmitFields2<typeof functionWithObjectParam, 'key1' | 'second'> // Okay
type Omitted6 = OmitFields2<string, 'first' | 'second'>
// TS2344 Type 'string' does not satisfy the constraint '(...args: any) => any'.