You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确引用父对象嵌套的LoginType作为方法参数类型?

解决嵌套对象属性作为TypeScript方法参数类型的问题

问题根源

  1. API是运行时值,并非TypeScript命名空间,直接用API.json.player.core.LoginType作为类型会触发TS2503错误——TypeScript无法从值的引用解析出对应类型。
  2. 将API.json.player.core.LoginType赋值给常量后直接用作类型,会触发TS2749错误——你把值当成了类型使用,即便用typeof获取值的类型,也会因GenericObject的宽泛约束导致类型信息丢失,无法得到具体的枚举成员类型。

正确实现方案

核心思路是先定义类型,再对齐值的实现,同时给API定义精确的结构接口,避免用过于宽泛的GenericObject抹平类型差异:

// 1. 分离LoginType的类型与运行时值
type LoginType = 'MANUAL_LOGIN' | 'CARDED_LOGIN' | 'CARDLESS_CONNECT_LOGIN';
const LoginTypeValues = {
  MANUAL_LOGIN: 'MANUAL_LOGIN' as const,
  CARDED_LOGIN: 'CARDED_LOGIN' as const,
  CARDLESS_CONNECT_LOGIN: 'CARDLESS_CONNECT_LOGIN' as const,
};

// 2. 定义API的逐层精确结构接口
interface ApiFunction extends GenericFunction {
  apiVersion: string;
  messageType: string;
  messageId: number;
  response: string;
  setMessageId: (messageId: number) => void;
  setResponse: (response: string) => void;
  username: string;
  password: string;
  cardNumber: string;
  loginType: LoginType;
  egmId: string;
}

interface PlayerCore {
  LoginType: typeof LoginTypeValues;
}

interface Player {
  core: PlayerCore;
}

interface Mfa {
  AuthenticateRequest: ApiFunction;
}

interface ApiJson {
  mfa: Mfa;
  player: Player;
}

interface API {
  json: ApiJson;
}

// 3. 保留原有GenericFunction定义
type GenericFunction = (...args: [Map<string, boolean | number | string>, number, string]) => void;

// 4. 初始化API并挂载LoginType值
const API: API = {
  json: {
    mfa: {} as Mfa,
    player: {
      core: {
        LoginType: LoginTypeValues,
      },
    },
  },
};

// 5. 实现AuthenticateRequest方法
API.json.mfa.AuthenticateRequest = function (
  this: ApiFunction,
  username: string,
  password: string,
  cardNumber: string,
  loginType: LoginType, // 直接使用预定义的类型
  egmId: string
): void {
  const self = this;
  this.apiVersion = '1.5-SNAPSHOT';
  this.messageType = 'AuthenticateRequest';
  this.setMessageId = (messageId: number): void => {
    self.messageId = messageId;
  };
  this.setResponse = (response: string): void => {
    self.response = response;
  };
  this.username = username;
  this.password = password;
  this.cardNumber = cardNumber;
  this.loginType = loginType;
  this.egmId = egmId;
} as unknown as GenericFunction;

关键改进点

  • 分离类型与值:LoginType作为联合类型约束参数,LoginTypeValues作为运行时值挂载到API结构中,兼顾类型检查与运行逻辑。
  • 精确接口定义:给API逐层定义接口,让TypeScript能准确推断每个嵌套属性的类型,避免GenericObject导致的类型信息丢失。
  • 直接使用预定义类型:方法参数直接用LoginType,既满足类型检查,又能获得完整的代码提示。

简化方案(无需完整接口)

如果不想编写多层API结构接口,可通过typeof推导精确类型,同时用as const保留值的字面量类型:

type GenericFunction = (...args: [Map<string, boolean | number | string>, number, string]) => void;

// 定义精确的LoginType值与推导类型
const LoginType = {
  MANUAL_LOGIN: 'MANUAL_LOGIN' as const,
  CARDED_LOGIN: 'CARDED_LOGIN' as const,
  CARDLESS_CONNECT_LOGIN: 'CARDLESS_CONNECT_LOGIN' as const,
};
type LoginType = typeof LoginType[keyof typeof LoginType];

// 初始化API,让TypeScript自动推断类型
const API = {
  json: {
    mfa: {},
    player: {
      core: {
        LoginType,
      },
    },
  },
};

// 定义ApiFunction接口
interface ApiFunction extends GenericFunction {
  apiVersion: string;
  messageType: string;
  messageId: number;
  response: string;
  setMessageId: (messageId: number) => void;
  setResponse: (response: string) => void;
  username: string;
  password: string;
  cardNumber: string;
  loginType: LoginType;
  egmId: string;
}

// 实现方法
API.json.mfa.AuthenticateRequest = function (
  this: ApiFunction,
  username: string,
  password: string,
  cardNumber: string,
  loginType: LoginType,
  egmId: string
): void {
  const self = this;
  this.apiVersion = '1.5-SNAPSHOT';
  this.messageType = 'AuthenticateRequest';
  this.setMessageId = (messageId: number): void => {
    self.messageId = messageId;
  };
  this.setResponse = (response: string): void => {
    self.response = response;
  };
  this.username = username;
  this.password = password;
  this.cardNumber = cardNumber;
  this.loginType = loginType;
  this.egmId = egmId;
} as unknown as GenericFunction;

此方案通过as const让LoginType值保留精确的字符串字面量类型,再用typeof LoginType[keyof typeof LoginType]生成对应的联合类型,同时依赖TypeScript自动推断API的结构类型,无需手动编写多层接口。

内容的提问来源于stack exchange,提问作者ar_IGT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 15:43:17