我在TypeScript中有以下界面:
interface IX {
a: string,
b: any,
c: AnotherType
}
Run Code Online (Sandbox Code Playgroud)
我声明了该类型的变量,并初始化了所有属性
let x: IX = {
a: 'abc',
b: null,
c: null
}
Run Code Online (Sandbox Code Playgroud)
然后我稍后在init函数中为它们分配实数值
x.a = 'xyz'
x.b = 123
x.c = new AnotherType()
Run Code Online (Sandbox Code Playgroud)
但是,我不希望在声明对象时,必须为每个属性指定一堆默认的空值,以便稍后将它们设置为实际值.我可以告诉界面默认我不提供给null的属性吗?什么会让我这样做:
let x: IX = {
a: 'abc'
}
Run Code Online (Sandbox Code Playgroud)
没有得到编译器错误.现在它告诉我
TS2322:类型"{}"不能分配给"IX"类型.类型"{}"中缺少属性"b".
bas*_*rat 75
我可以告诉界面默认我不提供给null的属性吗?什么会让我这样做
不,但默认情况下,它们undefined大多数都很好.您可以使用以下模式,即在创建时具有类型断言:
let x: IX = {} as any;
x.a = 'xyz'
x.b = 123
x.c = new AnotherType()
Run Code Online (Sandbox Code Playgroud)
我在这里记录了这个和其他模式:https://basarat.gitbooks.io/typescript/content/docs/tips/lazyObjectLiteralInitialization.html
小智 63
您不能在界面中设置默认值,但您可以使用可选属性完成您想要的操作(比较段落#3):
https://www.typescriptlang.org/docs/handbook/interfaces.html
只需将界面更改为:
interface IX {
a: string,
b?: any,
c?: AnotherType
}
Run Code Online (Sandbox Code Playgroud)
然后你可以这样做:
let x: IX = {
a: 'abc'
}
Run Code Online (Sandbox Code Playgroud)
并使用您的init函数为其分配默认值x.b,x.c如果未设置这些属性.
Nit*_*mer 18
您可以使用类实现接口,然后您可以在构造函数中处理初始化成员:
class IXClass implements IX {
a: string;
b: any;
c: AnotherType;
constructor(obj: IX);
constructor(a: string, b: any, c: AnotherType);
constructor() {
if (arguments.length == 1) {
this.a = arguments[0].a;
this.b = arguments[0].b;
this.c = arguments[0].c;
} else {
this.a = arguments[0];
this.b = arguments[1];
this.c = arguments[2];
}
}
}
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用工厂功能:
function ixFactory(a: string, b: any, c: AnotherType): IX {
return {
a: a,
b: b,
c: c
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以简单地说:
var ix: IX = null;
...
ix = new IXClass(...);
// or
ix = ixFactory(...);
Run Code Online (Sandbox Code Playgroud)
vit*_*ets 11
我使用以下模式:
创建实用程序类型Defaults<T>:
type OptionalKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? K : never }[keyof T];
type Defaults<T> = Required<Pick<T, OptionalKeys<T>>>
Run Code Online (Sandbox Code Playgroud)
使用选项/默认值声明类:
// options passed to class constructor
export interface Options {
a: string,
b?: any,
c?: number
}
// defaults
const defaults: Defaults<Options> = {
b: null,
c: 1
};
export class MyClass {
// all options in class must have values
options: Required<Options>;
constructor(options: Options) {
// merge passed options and defaults
this.options = Object.assign({}, defaults, options);
}
}
Run Code Online (Sandbox Code Playgroud)
创建类实例:
const myClass = new MyClass({
a: 'hello',
b: true,
});
console.log(myClass.options);
// { a: 'hello', b: true, c: 1 }
Run Code Online (Sandbox Code Playgroud)
Jac*_*ler 10
虽然@Timar的答案对于null默认值(要求的内容)非常有效,但是这里还有一个简单的解决方案,它允许其他默认值:定义一个选项接口以及一个包含默认值的常量;在构造函数中,使用传播运算符设置options成员变量
interface IXOptions {
a?: string,
b?: any,
c?: number
}
const XDefaults: IXOptions = {
a: "default",
b: null,
c: 1
}
export class ClassX {
private options: IXOptions;
constructor(XOptions: IXOptions) {
this.options = { ...XDefaults, ...XOptions };
}
public printOptions(): void {
console.log(this.options.a);
console.log(this.options.b);
console.log(this.options.c);
}
}
Run Code Online (Sandbox Code Playgroud)
现在您可以使用这样的类:
const x = new ClassX({ a: "set" });
x.printOptions();
Run Code Online (Sandbox Code Playgroud)
输出:
set
null
1
Run Code Online (Sandbox Code Playgroud)
小智 8
您可以Partial按照文档中的说明使用映射类型:https :
//www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html
在您的示例中,您将拥有:
interface IX {
a: string;
b: any;
c: AnotherType;
}
let x: Partial<IX> = {
a: 'abc'
}
Run Code Online (Sandbox Code Playgroud)
接口的默认值是不可能的,因为接口仅在编译时存在。
您可以为此使用工厂方法,该方法返回一个实现 XI 接口的对象。
class AnotherType {}
interface IX {
a: string,
b: any,
c: AnotherType | null
}
function makeIX (): IX {
return {
a: 'abc',
b: null,
c: null
}
}
const x = makeIX();
x.a = 'xyz';
x.b = 123;
x.c = new AnotherType();
Run Code Online (Sandbox Code Playgroud)
关于您的示例,我唯一更改的是属性 c Both AnotherType | null。这对于没有任何编译器错误是必要的(如果您将 null 初始化为属性 c,则您的示例中也存在此错误)。
如果您有许多参数,最佳实践是让用户仅插入几个参数并且不按特定顺序插入。
例如,不好的做法:
foo(a?, b=1, c=99, d=88, e?)
foo(null, null, null, 3)
Run Code Online (Sandbox Code Playgroud)
由于您必须在实际需要的参数之前提供所有参数 (d)。
良好的使用习惯是:
foo({d=3})
Run Code Online (Sandbox Code Playgroud)
做到这一点的方法是通过接口。您需要将参数定义为接口,例如:
interface Arguments {
a?;
b?;
c?;
d?;
e?;
}
Run Code Online (Sandbox Code Playgroud)
并将函数定义如下:
foo(arguments: Arguments)
Run Code Online (Sandbox Code Playgroud)
现在接口变量无法获取默认值,那么我们如何定义默认值呢?
很简单,我们为整个界面定义默认值:
foo({
a,
b=1,
c=99,
d=88,
e
}: Arguments)
Run Code Online (Sandbox Code Playgroud)
现在如果用户通过:
foo({d=3})
Run Code Online (Sandbox Code Playgroud)
实际参数将是:
{
a,
b=1,
c=99,
d=3,
e
}
Run Code Online (Sandbox Code Playgroud)
不声明接口的另一种选择是:
foo({
a=undefined,
b=1,
c=99,
d=88,
e=undefined
})
Run Code Online (Sandbox Code Playgroud)
跟进:
在前面的函数定义中,我们为参数对象的字段定义了默认值,但没有为对象本身定义默认值。Cannot read property 'b' of undefined因此,我们将从以下调用中得到提取错误(例如):
foo()
Run Code Online (Sandbox Code Playgroud)
有两种可能的解决方案:
1.
const defaultObject = {a=undefined, b=1, c=99, d=88, e=undefined}
function foo({a=defaultObject.a, b=defaultObject.b, c=defaultObject.c, d=defaultObject.d, e=defaultObject.e} = defaultObject)
Run Code Online (Sandbox Code Playgroud)
function foo(object = {}) {
object = { b=1, c=99, d=88, ...object }
//Continue the function code..
}
Run Code Online (Sandbox Code Playgroud)
跟进: 如果您需要类型和默认值(并且您不想声明接口),您可以编写:
function foo(params: {a?: string, b?: number, c?: number, d?: number, e?: string}) {
params = { b:1, c:99, d:88, ...params }
//Continue the function code..
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
136908 次 |
| 最近记录: |