打字稿:扩展接口并将现有字段重新声明为只读
Typescript: extending an interface and redeclaring the existing fields as readonly
假设我们有这样一个界面:
interface Person {
name: string;
age: number;
}
我想调用 Readonly 并创建接口的只读版本,例如
interface PersonReadonly extends Readonly<Person> {}
相当于写
interface PersonReadonly {
readonly name: string;
readonly age: number;
}
能不能写这样一个Readonly泛型接口,还是已经写好了?
从 TypeScript 2.1 开始,用于制作实例 readonly
的所有字段的通用接口可用。
它的名字恰好是 Readonly<T>
,因此您可以这样使用它:
let person: Readonly<Person> = { name: 'John', age: 30 };
person.age = 31; // gives error
在 TypeScript 2.1 之前不可能实现泛型只读类型。
在 playground 中定义了 Readonly
类型,因此您可以:
interface Person {
name: string;
age: number;
}
let a: Readonly<Person> = {
name: "name",
age: 3
};
a.age = 5; // Error: Cannot assign to 'age' because it is a constant or a read-only property
如果在您的环境中定义了该类型,那么您可以简单地添加它:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
}
但它要求你有 typescript 2.1 及以上版本。
如果你没有,那可能是你的typescript版本低于2.1,否则你可以直接使用。
回答你明确的问题:从技术上讲,你还不能做你想做的事。
类型映射将创建一个 Type
而不是接口 -- Readonly<T>
是一个内置的类型映射器,它将 return 一个 Type
。您不能实现或扩展 Type
别名,只能实现或扩展接口 / class。
因此:
interface PersonReadonly extends Readonly<Person> {}
在 support for implementing types are done 之前无效,如果有的话。
但这并不能阻止您传递 Type;您也可以在类型上使用 union 来构建更复杂的类型。因此你可以这样做:
type PersonWithState = Readonly<Person> & { state: string }
let person = <Person>{ name: "John", age: 20 };
let personState = <PersonWithState>{ ...person, state: "online" };
personState.age = "30"; // error;
personState.state = "offline"; // OK.
但是您还不能 class 实现或扩展接口,PersonWithState
。
你可以这样做:
type PersonReadonly = Readonly<Person>
但它不是一个接口。例如,您不能在其他地方添加新成员。
2017 年 5 月编辑:自 TS 2.2(2017 年 2 月)起,interfaces can be derived from types.
假设我们有这样一个界面:
interface Person {
name: string;
age: number;
}
我想调用 Readonly 并创建接口的只读版本,例如
interface PersonReadonly extends Readonly<Person> {}
相当于写
interface PersonReadonly {
readonly name: string;
readonly age: number;
}
能不能写这样一个Readonly泛型接口,还是已经写好了?
从 TypeScript 2.1 开始,用于制作实例 readonly
的所有字段的通用接口可用。
它的名字恰好是 Readonly<T>
,因此您可以这样使用它:
let person: Readonly<Person> = { name: 'John', age: 30 };
person.age = 31; // gives error
在 TypeScript 2.1 之前不可能实现泛型只读类型。
在 playground 中定义了 Readonly
类型,因此您可以:
interface Person {
name: string;
age: number;
}
let a: Readonly<Person> = {
name: "name",
age: 3
};
a.age = 5; // Error: Cannot assign to 'age' because it is a constant or a read-only property
如果在您的环境中定义了该类型,那么您可以简单地添加它:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
}
但它要求你有 typescript 2.1 及以上版本。
如果你没有,那可能是你的typescript版本低于2.1,否则你可以直接使用。
回答你明确的问题:从技术上讲,你还不能做你想做的事。
类型映射将创建一个 Type
而不是接口 -- Readonly<T>
是一个内置的类型映射器,它将 return 一个 Type
。您不能实现或扩展 Type
别名,只能实现或扩展接口 / class。
因此:
interface PersonReadonly extends Readonly<Person> {}
在 support for implementing types are done 之前无效,如果有的话。
但这并不能阻止您传递 Type;您也可以在类型上使用 union 来构建更复杂的类型。因此你可以这样做:
type PersonWithState = Readonly<Person> & { state: string }
let person = <Person>{ name: "John", age: 20 };
let personState = <PersonWithState>{ ...person, state: "online" };
personState.age = "30"; // error;
personState.state = "offline"; // OK.
但是您还不能 class 实现或扩展接口,PersonWithState
。
你可以这样做:
type PersonReadonly = Readonly<Person>
但它不是一个接口。例如,您不能在其他地方添加新成员。
2017 年 5 月编辑:自 TS 2.2(2017 年 2 月)起,interfaces can be derived from types.