类型转换表达式(Type Casting Expressions)
声明与转换值成各种类型
有时候并不需要像函数或变量一样声明类型,Flow支持内联类型转换表达式的语法。
类型转换语法
围绕一个值创建一个类型转换表达式的方式是:(:type)
。
(value: Type)
注:括号是避免与其他语法混淆的必要条件。
类型转换表达式可以在任何允许表达式存在的地方出现。
let val = (value: Type);
let obj = { prop: (value: Type) };
let arr = ([(value: Type), (value: Type)]: Array<Type>);
值本身可以是表达式:
(2 + 2: number);
类型声明
使用类型转换表达式,你可以把值声明成特定的类型。
// @flow
let value = 42;
(value: 42); // Works!
(value: number); // Works!
(value: string); // Error!
类型转换
当你编写一个类型转换表达式时,该表达式的结果是提供的值的类型。 并且会不断返回新的类型。
// @flow
let value = 42;
(value: 42); // Works!
(value: number); // Works!
let newValue = (value: number);
// $ExpectError
(newValue: 42); // Error!
(newValue: number); // Works!
通过any进行类型转换
由于类型转换与所有其他类型注释的工作方式相同,因此只能将值转换为较不具体的类型。你不能更改类型或使其更具体。
但是你可以使用any
类型来转换成你想要的任何类型。
let value = 42;
(value: number); // Works!
// $ExpectError
(value: string); // Error!
let newValue = ((value: any): string);
// $ExpectError
(newValue: number); // Error!
(newValue: string); // Works!
通过将值赋予任何值,然后可以转换成任何你想要的。这是不安全的,不推荐。但是当你做某些非常困难或不可能输入的值,并且要确保结果具有所需的类型时,有时候这会很有用。
例如,以下的cloneObject
函数。
function cloneObject(obj) {
const clone = {};
Object.keys(obj).forEach(key => {
clone[key] = obj[key];
});
return clone;
}
我们很难为此创建一个类型,因为我们正在创建一个基于另一个对象的新对象。但如果我们通过any
进行转换,我们可以返回一个更有用的类型。
// @flow
function cloneObject(obj) {
const clone = {};
Object.keys(obj).forEach(key => {
clone[key] = obj[key];
});
return ((clone: any): typeof obj); // <<
}
const clone = cloneObject({
foo: 1,
bar: true,
baz: 'three'
});
(clone.foo: 1); // Works!
(clone.bar: true); // Works!
(clone.baz: 'three'); // Works!
通过类型声明检查类型
如果你想验证上面提到的cloneObject
函数会接收什么类型,我们可以使用下面的注解:
function cloneObject(obj: { [key: string]: mixed }) {
// ...
}
但是typeof
对象注解会破坏整个目的。
// @flow
function cloneObject(obj: { [key: string]: mixed }) {
const clone = {};
// ...
return ((clone: any): typeof obj);
}
const clone = cloneObject({
foo: 1,
bar: true,
baz: 'three'
});
// $ExpectError
(clone.foo: 1); // Error!
// $ExpectError
(clone.bar: true); // Error!
// $ExpectError
(clone.baz: 'three'); // Error!
相反,我们通过使用类型声明表达式在函数内部进行声明。
// @flow
function cloneObject(obj) {
(obj: { [key: string]: mixed });
// ...
}
cloneObject({ foo: 1 }); // Works!
// $ExpectError
cloneObject([1, 2, 3]); // Error!
现在类型推导在type of
阶段作用,并且返回对象的形态。
// @flow
function cloneObject(obj) {
(obj: { [key: string]: mixed }); // <<
const clone = {};
// ...
return ((clone: any): typeof obj);
}
const clone = cloneObject({
foo: 1,
bar: true,
baz: 'three'
});
(clone.foo: 1); // Works!
(clone.bar: true); // Works!
(clone.baz: 'three'); // Works!
注意:这不是解决上述问题的恰当方法。 正确的解决方案是这样的注释功能:
function cloneObject<T: { [key: string]: mixed }>(obj: T): $Shape<T> {
// ...
}
网友评论