TypeScript中的嵌套对象

28

如何在TypeScript中声明像嵌套对象一样的JavaScript?

let endpoints = {
    auth: {
        login: "http://localhost:8079/auth/login"
    }
};
以下方法无效:

The following does not work:

private endpoints: Object = {
    auth: {
        login: "http://localhost:8079/auth/login"
    }
};

抛出:

错误 TS2339:对象类型上不存在属性“auth”。

4个回答

59

您可以使用接口:

interface EndpointAuth {
    login: string;
}

interface Endpoint {
    auth: EndpointAuth;
}

let endpoints: Endpoint = {
    auth: {
        login: "http://localhost:8079/auth/login"
    }
};

(在 playground 中查看代码)

您还可以使用类型代替接口:

type EndpointAuth = {
    login: string;
}

type Endpoint = {
    auth: EndpointAuth;
}
(在 playground 中查看代码)
或者 "内联":
let endpoints: { auth: { login: string } } = {
    auth: {
        login: "http://localhost:8079/auth/login"
    }
};

当然,你可以将它们组合在一起。


编辑

因为你想要答案解释为什么使用Object不起作用:

定义一个变量类型为Object(在大部分情况下)并不是你真正想做的,通常你的意思是any,就像这样:

var endpoints2: any = {
    auth: {
        login: "http://localhost:8079/auth/login"
    }
};

如果您不指定类型,它就不会失败(就像这样)。
将变量定义为Object与将其定义为{}相同,其为空对象,通常不是您想要的,而且仅适用于以下情况:

let o1: Object = {};
let o2: Object = Object.create(null);

然而,使用any并不能帮助你太多,因为这样你基本上告诉编译器不必担心类型安全,它将允许你对变量做任何操作,却不告知你是否存在错误:

let o: any = { x: 3, y: 6 };
console.log(o.z.toString());

编译不会失败,但运行时会失败:

未捕获的类型错误:无法读取未定义的属性'toString'

这将在编译时失败:

let o: { x: number, y: number } = { x: 3, y: 6 };
console.log(o.z.toString());

2
我将这个标记为正确答案,因为它是最全面的。然而,Amir也对错误的本质给出了解释。如果你愿意,你可以把这部分加入到你的答案中。 - Samuel
2
可以,添加了详细的解释。 - Nitzan Tomer
let o2: Object = Object.create(null) 是不正确的,因为你在说 o2 的类型是一个以 Object 为原型的对象,但是 o2 的原型是 null。 - Jordan

17
你可以声明一个接口。
对于你的情况。
interface IEndpoints
{
 auth: {
  login: string;
 }
}
private endpoints: IEndpoints = {
  auth: {
    login: "http://localhost:8079/auth/login"
  }
};

5
这可能是更好的答案。为什么要定义两个接口/类型,当你只需要一个就可以了! - spechter

8

我不知道您过去使用的是哪个 TypeScript 版本,但目前已支持此功能。

interface Endpoints {
  [path: string]: Endpoints | string
}

const endpoints: Endpoints = {
    auth: {
        login: "http://localhost:8079/auth/login"
    }
}

1
完美 - Aleks
我总是在使用Record<>时遇到困难,因为它不能处理像{[path: string]: type}这样的递归类型 :( - derpedy-doo

4

如果您想要类型安全,需要创建自定义的类或接口:

interface IMyInterface
{
    auth: IAuth;
}

interface IAuth
{
    login: string;
}

private endpoints: IMyInterface= {
    auth: {
        login: "http://localhost:8079/auth/login"
    }
};

你的错误原因是你声明了类型为 Object 的端点,而 Object 没有 auth 属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接