打字稿说我的对象缺少属性,因为它并不缺少

发布于 2025-02-01 05:20:44 字数 1149 浏览 3 评论 0原文

我正在研究一个具有以下模式的项目:

interface IAuthProvider {
  middleware: () => void
  getInput: () => void
}

class Password implements IAuthProvider {
  middleware = () => {}
  getInput = () => {}
}

class Email implements IAuthProvider {
  middleware = () => {}
  getInput = () => {}
}

const providerNames = ['Email', 'Password']

type AuthProviderNamespace = { [K in typeof providerNames[number]]: IAuthProvider }

// error: Type 'typeof Password' is missing the following properties from type 'IAuthProvider': middleware, getInput
const providers: AuthProviderNamespace = { Email, Password }

这种对象将在模块中导入并直接传递到将遍历它的函数:

import * as AuthProviders from './providers/index.ts'

const providers = instantiateProviders(AuthProviders)

我需要使用authprovidernamespace,因为 我需要键入authProviders。但是我做错了一些事情,因此Typescript无法将电子邮件和密码识别为IAUTHPROVIDER的实施者。我可以解决这个问题吗?

游乐场: https://tsplay.dev/wqv7jn

I'm working on a project that has the following pattern:

interface IAuthProvider {
  middleware: () => void
  getInput: () => void
}

class Password implements IAuthProvider {
  middleware = () => {}
  getInput = () => {}
}

class Email implements IAuthProvider {
  middleware = () => {}
  getInput = () => {}
}

const providerNames = ['Email', 'Password']

type AuthProviderNamespace = { [K in typeof providerNames[number]]: IAuthProvider }

// error: Type 'typeof Password' is missing the following properties from type 'IAuthProvider': middleware, getInput
const providers: AuthProviderNamespace = { Email, Password }

I need to use AuthProviderNamespace because this kind of object will be imported in a module and passed directly to a function that will iterate over it:

import * as AuthProviders from './providers/index.ts'

const providers = instantiateProviders(AuthProviders)

And so I need to type AuthProviders. But I'm doing something wrong such that typescript doesn't recognize Email and Password as implementers of IAuthProvider. Can I fix this?

Playground: https://tsplay.dev/wQV7jN

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

江心雾 2025-02-08 05:20:44

错误是正确的。值{电子邮件:电子邮件,密码:密码}是一个对象,其属性为iauthprovider对象的每个构造函数。但是类型{email:iauthprovider,密码:iauthprovider}对应于emaim> email> emailpassword properties的对象iauthprovider 实例,而不是此类实例的构造函数。类构造函数电子邮件没有getInput属性,因此它不能是iauthprovider

Email.getInput; // <-- error, Property 'getInput' does not exist on type 'typeof Email'

假设您使用提供者是使用其属性来构建iauthprovider的新实例,如下:

const provider = new providers.Email(); // note, assuming a no-arg constructor
provider.getInput(); // okay
provider.middleware(); // okay

然后,您需要更改authprovidernamespace type type,以便其属性是iauthprovider 实例。您可以使用构造签名{new():iauthprovider} 或喜欢new()=&gt; IAuthProvider:

type AuthProviderNamespace = {
  [K in typeof providerNames[number]]: new () => IAuthProvider
}

And then everything works as desired:

const providers: AuthProviderNamespace = { Email, Password }

The error is correct. The value {Email: Email, Password: Password} is an object whose properties are each constructors of IAuthProvider objects. But the type {Email: IAuthProvider, Password: IAuthProvider} corresponds to an object whose Email and Password properties are IAuthProvider instances, not constructors of such instances. The class constructor Email does not have a getInput property, so it cannot be an IAuthProvider:

Email.getInput; // <-- error, Property 'getInput' does not exist on type 'typeof Email'

Assuming your intent with providers is to use its properties to construct new instances of IAuthProvider, like this:

const provider = new providers.Email(); // note, assuming a no-arg constructor
provider.getInput(); // okay
provider.middleware(); // okay

Then you need to change the AuthProviderNamespace type so that its properties are no-arg constructors of IAuthProvider instances. You can use a construct signature like { new(): IAuthProvider } or like new () => IAuthProvider:

type AuthProviderNamespace = {
  [K in typeof providerNames[number]]: new () => IAuthProvider
}

And then everything works as desired:

const providers: AuthProviderNamespace = { Email, Password }

Playground link to code

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文