首页 > 解决方案 > 为什么 setter 函数接受与其在打字稿中的字段相同的数据类型?

问题描述

我正在尝试使用 setter 函数将字符串值插入到打字稿类中的私有数组中。在我的 getter 函数中,intellisense 表示返回的值是类型不匹配,如下面的代码中所述。

export class Player{
    constructor(private _skills:string[]){}

    get skills(){
        return this._skills  // Type string not assignable to type string[]
    }

    set skills(newSkill:string){
        this._skills = [...this._skills,newSkill]
    }
}

在将显式函数参数类型删除newSkill:string为 justnewSkill时,上述错误得到解决,因为 typescript 期望在 setter 中传递一个字符串数组,而不仅仅是一个字符串。

我们可以通过将单个字符串包含在一个数组中来插入一个字符串,然后将传递的数组与私有数组字段合并。

player.skills = ["single skill"]
export class Player{
    constructor(private _skills:string[]){}

    get skills(){
        return this._skills
    }

    set skills(newSkill){
        this._skills = [...this._skills,...newSkill]
    }
}

但是,对于我们需要一次只向技能数组而不是技能数组插入一个技能值的情况,为什么我们应该将一个数组而不只是一个字符串传递给 setter 函数呢?

为什么只有一个字符串而不只是字符串(作为 setter 函数中的数据类型)的数组是问题所在?

是否可以避免字符串数组数据类型并将其设置为字符串数据类型?

注意:要求是使用 typescript 的 set 关键字一次插入/设置一个字符串值,而不是值数组到技能数组

标签: typescript

解决方案


它与领域无关。skills和之间没有内在联系_skills。要求是 getter 的返回类型必须与 setter 的参数类型匹配。

可以使用联合类型来处理它:

export class Player {
    constructor(private _skills: string[]) {
    }

    get skills() {
        return this._skills;
    }

    set skills(newSkill: string[] | string) {
        if (typeof newSkill === "string") {
            this._skills.push(newSkill);
        } else {
            this._skills = newSkill.slice(); // Note: Completely replaces the value
        }
    }
}

...但你不应该,有几个原因:

  1. 每次使用 getter 时都必须检查它得到的是字符串还是字符串数组,即使它总是返回一个数组。

  2. 非对称 API 已被充分证明难以学习和使用(想想document.cookie不寒而栗)。(上面的 API 实际上是不对称的,即使它没有定义,因为 getter 总是返回一个数组。)

相反,如果您希望技能成为一个数组,请将其设为一个数组,并使用一种方法可以让您添加单个技能或添加一组技能:

export class Player {
    constructor(private _skills: string[]) {
    }

    // Gets the array of skills -- you might want to make a
    // defensive copy, or return a frozen version or similar
    get skills() {
        return this._skills;
    }

    // Sets the array of skills, OVERWRITING previous ones
    set skills(newSkills: string[]) {
        this._skills = newSkills.slice();
    }

    // Adds one or more skills, which can be given as individual
    // strings or arrays of strings
    addSkills(...skills: (string|string[])[]) {
        // Add all the skills, which 
        this._skills.push(...skills.flat());
    }
}

(注意:使用新flat方法。)


推荐阅读