未定义数组的推断

问题描述 投票:0回答:1
interface Foo {
  a: number;
  b: string;
}

function augment<T>() {
  return <A extends keyof T>(actions?: A[]) => {
    const C = class {
      // some code here that is irrelevant for my issue
    };

    return C as unknown as new () => InstanceType<typeof C> & Pick<T, A>;
  };
}

const Class = augment<Foo>()(["a", "b"]);
const instance: InstanceType<typeof Class> = new Class();

// 👍 instance.a and instance.b are available, as expected

const Class2 = augment<Foo>()([]);
const instance2: InstanceType<typeof Class2> = new Class2();

// 👍 instance2.a and instance.b do no exist

const Class3 = augment<Foo>()();
const instance3: InstanceType<typeof Class3> = new Class3();

// 👎 instance3.a is available even if I didn't pass any actions :-(

augment
中,我使用
actions
参数来推断
A
类型。

它适用于

Foo
的任何属性,但是当我不通过某些操作时,就像推理类型推断出
A
keyof T
.

我知道我可以传递一个空数组,但我真的希望有可能不为我的函数传递任何操作,有没有办法做到这一点?

typescript type-inference
1个回答
2
投票

这是因为如果无法推断

A
,TypeScript 将默认使用其泛型约束类型。幸运的是,您可以通过提供默认值来覆盖此行为。如果因为没有为
A
传递任何内容而无法推断出
actions
,您可以默认为
never

function augment<T>() {
  return <A extends keyof T = never>(actions?: A[]) => {
//                         ~~~~~~~~ defaults to `never` if `A` cannot be inferred
    const C = class extends EventEmitter {};

    return C as unknown as new () => InstanceType<typeof C> & Pick<T, A>;
  };
}

然后,在第三个例子中,你会得到错误,因为它现在正在使用

Pick<Foo, never>

const Class3 = augment<Foo>()();
const instance3: InstanceType<typeof Class3> = new Class3();
instance3.a; // error
instance3.b; // error

游乐场

© www.soinside.com 2019 - 2024. All rights reserved.