函数参数接受其类型之一是类型缩小的类类型

时间:2019-03-25 07:42:00

标签: typescript

类具有联合类型属性。函数接受带有类型限制属性的此类。我可以定义这样的功能吗?

我有一个登录表格。用户需要输入电话,并相应地输入密码或短信代码。这是登录表单类的定义。

export class PhoneLoginForm {
    public phone: string;
    public authForm: PhonePasswordLoginForm | PhoneSmsLoginForm;
}

export class PhonePasswordLoginForm {
    public password: string;
    public captcha: string;
}

export class PhoneSmsLoginForm {
    public sms: string;
}

还有过程功能

public onLogin(loginForm: PhoneLoginForm) {
    if (loginForm.authForm instanceof PhonePasswordLoginForm) {
        processPhonePasswordForm(loginForm);
    } else {
        processPhoneSmsForm(loginForm);
    }
}

// How to constrain loginForm.authForm is PhonePasswordLoginForm ?
public processPhonePasswordForm(loginForm: PhoneLoginForm) {
    // Authenticate with loginForm.phone, loginForm.authForm.password, loginForm.authForm.captcha.
}

// How to constrain loginForm.authForm is PhoneSmsLoginForm ?
public processPhoneSmsForm(loginForm: PhoneLoginForm) {
    // Authenticate with loginForm.phone, loginForm.authForm.sms.
}

我在打字稿文档或github问题中找不到此语法。可以定义这样的功能吗?

谢谢您的回答!

1 个答案:

答案 0 :(得分:2)

这就是我要怎么做。

首先,必须完全根据需要定义类型:

export type PhoneLoginForm = PhoneLoginFormWithSms | PhoneLoginFormWithPassword;

export interface PhoneLoginFormWithSms {
    phone: string;
    authForm: PhoneSmsLoginForm;
}

export interface PhoneSmsLoginForm {
    sms: string;
}

export interface PhoneLoginFormWithPassword {
    phone: string;
    authForm: PhonePasswordLoginForm;
}

export interface PhonePasswordLoginForm {
    password: string;
    captcha: string;
}

Type guards可以实现:

export function isPhoneLoginFormWithSms(loginForm: PhoneLoginForm): loginForm is PhoneLoginFormWithSms {
    return !!loginForm.authForm["sms"]
}

export function isPhoneLoginFormWithPassword(loginForm: PhoneLoginForm): loginForm is PhoneLoginFormWithPassword {
    return loginForm.authForm["password"] !== undefined
}

现在可以轻松使用以下类型:

function onLogin(loginForm: PhoneLoginForm) {
    if (isPhoneLoginFormWithPassword(loginForm)) {
        processPhonePasswordForm(loginForm);
    } else {
        processPhoneSmsForm(loginForm);
    }
}

function processPhonePasswordForm(loginForm: PhoneLoginFormWithPassword) {
}

function processPhoneSmsForm(loginForm: PhoneLoginFormWithSms) {
}

关于您的类型的实现,例如带有类的示例:

class PhoneLoginFormWithSmsImpl implements PhoneLoginFormWithSms { 
  constructor(public phone: string, public authForm: PhoneSmsLoginForm) {
  }
}

class PhoneLoginFormWithPasswordImpl implements PhoneLoginFormWithPassword { 
  constructor(public phone: string, public authForm: PhonePasswordLoginForm) {
  }
}