- Original Address: the typescript 3.0: Type at The Unknown
- Original author: Marius Schulz
- Translation from: Nuggets Translation Project
- Permalink article: github.com/xitu/gold-m...
- 译者: Shixi-Li
- Proofreaders: Usey95 , smilemuffie
TypeScript 3.0 introduces a new unknown
type, which is any
corresponding to the type of security type.
unknown
And any
the main difference is that unknown
type will be more strict: On the unknown
Before most value type of operation, we have some form of inspection. In the pair any
before the operation value types, we do not carry out any checks.
This article focuses on the unknown
practical application type, and contains the any
kind of comparison. If a more comprehensive code example to understand unknown
the type of semantics, Anders Hejlsberg can see the original request for pulling .
any
Types of
Let's first look at any
the type, so that we can better understand the introduction of unknown
the motivation behind the type.
Since TypeScript released the first version in 2012 any
type it has been in existence. It represents all possible values of JavaScript - basic types, objects, arrays, functions, Error, Symbol, and any value you may define.
In TypeScript, any type can be classified as any type. This makes any
the type of system has become a type of top-level type (also referred to as a global super type ).
This is something we assigned to the any
code sample types:
let value: any;
value = true; // OK
value = 42; // OK
value = "Hello World"; // OK
value = []; // OK
value = {}; // OK
value = Math.random; // OK
value = null; // OK
value = undefined; // OK
value = new TypeError(); // OK
value = Symbol("type"); // OK
复制代码
any
Type system is an escape chamber of the type in nature. As a developer, this gives us a lot of freedom: TypeScript allows us to any
value types do anything, without first performing any form of censorship.
In the above example, the variables value
are defined as types any
. Is, therefore, TypeScript think all of the following types of operations are correct:
let value: any;
value.foo.bar; // OK
value.trim(); // OK
value(); // OK
new value(); // OK
value[0][1]; // OK
复制代码
Under so many scenarios, such mechanisms are too loose. Use any
type, you can easily write the correct type but the abnormality code. If we use any
type, you will not enjoy TypeScript a large number of protection mechanisms.
But if there is a default top-level type can be kept safe? This is the unknown
reason for coming.
unknown
Types of
Like all types can be classified as any
, all types also can be classified as unknown
. This makes it unknown
be another type TypeScript top type system (the other is any
).
This is the same set of assignment examples we have seen before, this time using type unknown
variables:
let value: unknown;
value = true; // OK
value = 42; // OK
value = "Hello World"; // OK
value = []; // OK
value = {}; // OK
value = Math.random; // OK
value = null; // OK
value = undefined; // OK
value = new TypeError(); // OK
value = Symbol("type"); // OK
复制代码
For value
all variable assignments are considered to be the correct type.
When we try to type unknown
when assigning values to other types of variables What will happen?
let value: unknown;
let value1: unknown = value; // OK
let value2: any = value; // OK
let value3: boolean = value; // Error
let value4: number = value; // Error
let value5: string = value; // Error
let value6: object = value; // Error
let value7: any[] = value; // Error
let value8: Function = value; // Error
复制代码
unknown
Type can only be assigned to any
type and unknown
type itself. Intuitively, this makes sense: only be able to save any type of container value to save unknown
value types. After all, we do not know the variables value
are stored in what type of value.
Now let's see when we try to type unknown
the value of performing an operation what happens. The following operation is the same as we've seen before:
let value: unknown;
value.foo.bar; // Error
value.trim(); // Error
value(); // Error
new value(); // Error
value[0][1]; // Error
复制代码
The value
variable type is set unknown
later, these operations are no longer considered to be the correct type. By changing the any
type to unknown
type, has become our default setting allows almost anything does not allow everything from flip-style change.
This is the unknown
type of main value propositions: TypeScript does not allow us to type unknown
values to perform any operations. Instead, we must first perform some type checking to narrow the range of values of the type we are using.
Narrow unknown
Type Range
We can in different ways be unknown
the type more specific narrow range of types, including typeof
operators, instanceof
operators, and custom type protection function. All of these types of narrow ranges of technologies contribute TypeScript based on the type of control flow analysis .
The following example shows value
how the two if
get more specific type statement branch:
function stringifyForLogging(value: unknown): string {
if (typeof value === "function") {
// Within this branch, `value` has type `Function`,
// so we can access the function's `name` property
const functionName = value.name || "(anonymous)";
return `[function ${functionName}]`;
}
if (value instanceof Date) {
// Within this branch, `value` has type `Date`,
// so we can call the `toISOString` method
return value.toISOString();
}
return String(value);
}
复制代码
In addition to the use typeof
or instanceof
addition operator, we can also use a custom type of the protecting function narrow unknown
range of types:
/**
* A custom type guard function that determines whether
* `value` is an array that only contains numbers.
*/
function isNumberArray(value: unknown): value is number[] {
return (
Array.isArray(value) &&
value.every(element => typeof element === "number")
);
}
const unknownValue: unknown = [15, 23, 8, 4, 42, 16];
if (isNumberArray(unknownValue)) {
// Within this branch, `unknownValue` has type `number[]`,
// so we can spread the numbers as arguments to `Math.max`
const max = Math.max(...unknownValue);
console.log(max);
}
复制代码
Although unknownValue
that has been classified as a unknown
type, please note that it is still how to get in if the branch number[]
type.
Of unknown
type using the type of assertion
In the previous section, we have seen how to use typeof
, instanceof
and customize the type of protection function to convince TypeScript compiler has a value of some type. This is a designated "unknown" type to a more specific type of security and recommended approach.
If you want to force the compiler to trust type unknown
of the value of a given type, you can use something like this type of assertion:
const value: unknown = "Hello World";
const someString: string = value as string;
const otherString = someString.toUpperCase(); // "HELLO WORLD"
复制代码
Please note, TypeScript in fact did not do anything special checks to make sure the type of assertion in fact valid. Type checker assumes that you know more about any type you use and believe in the type of assertion is correct.
If you make a mistake and specify the type of error, which can easily result in an error at runtime:
const value: unknown = 42;
const someString: string = value as string;
const otherString = someString.toUpperCase(); // BOOM
复制代码
This value
variable is a numeric value, but we assume it is a string and use the type of assertion value as string
. Use it with caution types assertion!
Joint types unknown
Type
Now let's look at how to handle union types in unknown
type. In the next section, we will also learn cross type.
In union types, the unknown
type will absorb any type. This means that if either type is composed of unknown
joint type will be the equivalent of unknown
:
type UnionType1 = unknown | null; // unknown
type UnionType2 = unknown | undefined; // unknown
type UnionType3 = unknown | string; // unknown
type UnionType4 = unknown | number[]; // unknown
复制代码
An accident of this rule is any
the type. If the type is composed of at least one any
joint type will be the equivalent of any
:
type UnionType5 = unknown | any; // any
复制代码
So why unknown
can absorb any type ( any
except type)? Let's think about unknown | string
this example. This type can represent any type or string type value of unkown. As we learned before, the value of all types can be defined as unknown
type, including all string
types, therefore, unknown | string
is to represent and unknown
type itself same set of values. Therefore, the compiler could be simplified type of joint unknown
type.
CROSS types unknown
Type
In the cross type, it can be any type of absorption unknown
type. This means that any type of unknown
intersection will not change the result type:
type IntersectionType1 = unknown & null; // null
type IntersectionType2 = unknown & undefined; // undefined
type IntersectionType3 = unknown & string; // string
type IntersectionType4 = unknown & number[]; // number[]
type IntersectionType5 = unknown & any; // any
复制代码
Let's recap IntersectionType3
: unknown & string
type represents everything that can be assigned to the same time unknown
and string
value types. Since each type can be assigned to unknown
the type, the type contained in the intersection unknown
does not change the result. We will only string
types.
Use of type unknown
value operator
unknown
Value type can not be used as operands of most operators. This is because if we do not know the type of value we are using, most operators are unlikely to produce meaningful results.
You can type unknown
used on the value of the operator only four equality and inequality operators:
===
==
!==
!=
If you want to type unknown
using any other operator value, you must specify the type (or types to use assertion to force the compiler to trust you).
Example: From localStorage
reading the JSON
This is how we use unknown
real examples of the type.
Suppose we want to write a slave localStorage
and anti-serialized to JSON functions read value. If the item does not exist or is not valid JSON, the function should return incorrect results, otherwise, it should deserialize and return values.
Because we do not know when deserializing JSON string persistence of what type of value we would get. We will use unknown
as an anti-serialized value types. This means that we function call must be some form of checks (or use a type of assertion) prior to the return value of the operation.
Here we show how to achieve this function:
type Result =
| { success: true, value: unknown }
| { success: false, error: Error };
function tryDeserializeLocalStorageItem(key: string): Result {
const item = localStorage.getItem(key);
if (item === null) {
// The item does not exist, thus return an error result
return {
success: false,
error: new Error(`Item with key "${key}" does not exist`)
};
}
let value: unknown;
try {
value = JSON.parse(item);
} catch (error) {
// The item is not valid JSON, thus return an error result
return {
success: false,
error
};
}
// Everything's fine, thus return a success result
return {
success: true,
value
};
}
复制代码
Return type Result
is a combined type is marked . In other languages, it can also be referred to Maybe
, Option
or Optional
. We used Result
to clear the result of successful and unsuccessful operations simulation.
tryDeserializeLocalStorageItem
Function calls are attempting to use value
or error
must first check the property before the success
property:
const result = tryDeserializeLocalStorageItem("dark_mode");
if (result.success) {
// We've narrowed the `success` property to `true`,
// so we can access the `value` property
const darkModeEnabled: unknown = result.value;
if (typeof darkModeEnabled === "boolean") {
// We've narrowed the `unknown` type to `boolean`,
// so we can safely use `darkModeEnabled` as a boolean
console.log("Dark mode enabled: " + darkModeEnabled);
}
} else {
// We've narrowed the `success` property to `false`,
// so we can access the `error` property
console.error(result.error);
}
复制代码
Note that tryDeserializeLocalStorageItem
the function can not simply by returning null
represented deserialized failure, for the following reasons:
null
Value is a valid JSON value. Therefore, we can not distinguish between the valuesnull
were deserialized or because of a lack of parameters or syntax errors cause the entire operation to fail.- If we return from the function
null
, we can not return an error at the same time. Therefore, we call those functions do not know why the operation failed.
For completeness, a more sophisticated alternative to this approach is to use the type of decoder for secure JSON parsing. We expect the decoder needs to specify the data structure value deserialized. If persistent JSON results do not match the data structure, the decoding failure will be well-defined way. In this way, our function always returns valid or failure of decoding result, you no longer need to unknown
type up.
If you find there is a translation error or other areas for improvement, welcome to Denver translation program to be modified and translations PR, also obtained the corresponding bonus points. The beginning of the article Permalink article is the MarkDown the links in this article on GitHub.
Nuggets Translation Project is a high-quality translation of technical articles Internet community, Source for the Nuggets English Share article on. Content covering Android , iOS , front-end , back-end , block chain , product , design , artificial intelligence field, etc., you want to see more high-quality translations, please continue to focus Nuggets translation program , the official micro-blog , we know almost columns .
Reproduced in: https: //juejin.im/post/5d04ac745188250a8b1fd203