强制函数只接受特定结构的对象(在typescript / js中)

时间:2017-07-23 08:08:58

标签: javascript typescript javascript-objects type-safety

我知道打字稿的一些优点是能够实现类型安全功能 -
但是有可能确保我的函数只能获取具有特定键的对象,换句话说 - 具体结构的对象?

我知道有许多优雅的方法来测试是否存在嵌套键,例如[this one] [1],
我当然可以在我的函数开头做一个小检查 - 但我之所以这样问是因为我的函数将被许多其他程序员使用 - 我想确保他们能够理解他们应该输入什么样的输入只从函数的签名中插入。

示例:

function printName(user){
    console.log(user.details.name); // I want to ensure details.name exist
}

我希望有一些功能:

function (user : {details: {name : string}}){
    //same ...
}


[1]: https://stackoverflow.com/questions/2631001/javascript-test-for-existence-of-nested-object-key#answer-4034468 "this one"

4 个答案:

答案 0 :(得分:2)

interface User {
    details:{name: string}
}

function printName(user:User){
    console.log(user.details.name); // I want to ensure details.name exist
}

答案 1 :(得分:0)

这正是您所希望的功能:

function printName(user: { [key: string]: any, details: { [key: string]: any, name: string }}) {
    console.log(user.details.name)
}

允许任何属性需要details + name

更清晰易读并防止意外更改:

// oftentimes you put the following interfaces in extra files:
interface Details {
    readonly [key: string]: any // = allow other properties than "name"*
    readonly name: string
}
interface User {
    readonly [key: string]: any // = allow other properties than "details"*
    readonly details: Details
}
// *) consider explicitly specifying them

function printName(user: User) {
    console.log(user.details.name)
}

如果您知道其他开发人员可以使用纯JavaScript代码(而不是TypeScript代码)调用您的函数,请使用以下代码:

function printName(user: User) {
    const name = ((user || <User>{}).details || <Details>{}).name
    if(name == void 0) {
        console.error("user name missing")
    }
    console.log(name)
}

Code on TypeScript Playground

答案 2 :(得分:0)

如果您想从特定属性中检索值,请使用 keyof,这将突出显示不正确的属性名称。

您也可以使用 Object.keys 来检查该属性是否存在。

interface UserProps {
  name: string;
  age: number;
}

export class User {
  constructor(private data: UserProps) {}

  get(propName: keyof UserProps): string | number {
    const dataKeys = Object.keys(this.data);
    if (!dataKeys.includes(propName)) {
      throw Error(`Property ${propName} does not exists on user object`);
    }
    return this.data[propName];
  }
}

答案 3 :(得分:-1)

您可以使用typescript

中的界面
export interface Details{
  name:string,
  age: number
}
export interface User{
  details :  {
        [key: string]: Details
    };
}

function printName(user : User){}