我有一个对象,仅使用一次,只有三个属性,但是每个属性应为同一类型。以下内容对我有用,但我想知道是否有更有效的方法来声明timingsObject
的类型:
let timingsObject:
{ start: null | string, end: null | string, length: null | string } =
{ start: null, end: null, length: null }
// ... later on timeingsArray is of string[] type
timingsObject.start = timingsArray[0];
timingsObject.end = timingsArray[1];
timingsObject.length = timingsArray[2];
答案 0 :(得分:2)
我可以想到两种替代方法。通用类型或预定义类型。
interface IObject<T> {
start: T
end: T
length: T
}
type myType = string | null
interface IObject2 {
start: myType
end: myType
length: myType
}
let timingsObject: IObject<string | null> = { start: null, end: null, length: null }
let timingsObject: IObject2 = { start: null, end: null, length: null }
答案 1 :(得分:1)
坏
您可以将形状定义为
interface Timings {
start: string | null;
end: string | null;
length: string | null;
}
但是该设计无法正确表达您的问题。例如,{ start: string, end: null, length: null }
在类型级别上是正确的,但是在程序中表示无效状态。
如果要这样做:
if (timingsObject.start) {
typeof timingsObject.length.toString(); // Compile-type error!
}
我们知道timingsObject.length
是一个字符串,但TypeScript不是。在使用timingsObject
的任何其他属性之前,需要先将其验证为string
。
好
将问题建模为两个状态的总和。第一个是定义明确的:
interface Timings {
start: string;
end: string;
length: string;
}
第二个是它的空等效项。您输入的是一个或另一个,可以表示为:
declare const timings: Empty<Timings> | Timings;
我们如何建模Empty
?让我们将其设置为映射类型,将所有内容转换为null
。
type Empty<T> =
T extends object
? { [K in keyof T]: null }
: null
declare function isEmpty<T>(argument: T | Empty<T>): argument is Empty<T>;
现在,编译器知道,如果一个属性是一个字符串,那么其他所有属性也都是一个字符串。
if (!isEmpty(timings)) {
timings.start + timings.end; // Both are known to be strings!
}
此解决方案可能看起来确实可行(确实如此),但它成功地将您的域问题烘烤到了类型系统中。
答案 2 :(得分:0)
由于计时对象的所有属性要么全部都是字符串,要么全部都是伪造的(并且实际上未在此状态下使用),并且由于所有属性都只应用于一个位置,所以我们也可以:
interface Timings {
start: string;
end: string;
length: string;
}
let timings?: Timings; // could also use let timings: Timings | null = null;
// do other things ...
timings = {
start: "someValue",
end: "someOtherValue,
length: "yetAnotherValue"
};