Home >
Article > Web Front-end > Share a good TS interview question (including 3 levels) and see which level you can answer!
Share a good TS interview question (including 3 levels) and see which level you can answer!
青灯夜游forward
2023-01-13 20:05:292585browse
I recently came across a good TS interview question and would like to share it.
This question has 3 levels, let’s look at them one by one.
The requirements for the first level are as follows:
Implement a zip function to merge the elements of two arrays in order, such as input [1,2,3] , [4,5,6], return [[1,4], [2,5],[3,6]]
This layer is to fetch from two arrays each time After merging an element, put it into the array, and then continue processing the next one, and continue this process recursively until the array is empty.
The first level is relatively simple, then let’s look at the second level requirements:
Define the ts type for this zip function (two writing methods)
There are two forms of function definition:
Declare the function directly through function:
function func() {}
And declare an anonymous function and assign it to a variable:
const func = () => {}
The types of parameters and return values are both arrays, but the specific types are not known, so you can write unknown[].
So the definition of the two function types is like this:
is also a direct function declaration of function type and interface declaration The function type is then added to the variable type both ways.
Because the specific element type is not known, unknown is used.
You may ask here the difference between any and unknown:
Both any and unknown can receive any type:
But any can also Assign to any type, but unknown.
This is only used to receive other types, so unknown is more appropriate and safer than any.
This level is also relatively basic ts syntax, and the third level becomes more difficult:
Use type programming to achieve precise type hints, such as passing parameters in [1, 2,3], [4,5,6], then the type of the return value should be prompted as [[1,4], [2,5],[3,6]]
here If the return value type is required to be precise, we must dynamically generate the return value type based on the type of the parameter.
That's it:
Declare two type parameters Target and Source, and the constraint is unknown[], which is an array type of any element type.
These two type parameters are the types of the two parameters passed in.
The return value is calculated by Zip.
Then we need to implement the advanced type of Zip:
The type parameters passed in are two array types, and we also need to extract each element from them and merge them together.
Pattern matching can be used to extract elements:
So this type can be defined like this:
type Zip =
One extends [infer OneFirst,...infer Rest1]
? Other extends [infer OtherFirst, ...infer Rest2]
? [[OneFirst, OtherFirst], ...Zip]
: []
: [];
Extract the first elements of the two arrays respectively and construct a new array. Then do this recursively for the remaining array until the array is empty.
This achieves the advanced type we want:
#But if you add it as a return value to the function, an error will be reported:
Because we don’t know what the parameters are when we declare the function, we naturally cannot calculate the value of Zipa7808be3c0f211b573c7d3497f62053f, so there will be a type mismatch here:
then what should we do?
can be solved by function overloading:
#ts supports function overloading. You can write the type definition of multiple types of functions with the same name, and finally write the function's Implementation, so that when this function is used, the function type will be matched according to the type of the parameter.
The function we use type programming will not report an error if it is written in this way.
Let’s take a look:
Why is the return value type wrong?
#In fact, the matching function type is correct at this time, but the deduced type is not a literal type.
You can add as const at this time.
But adding as const will deduce readonly [1,2,3]
This type is not It matches, so we need to add readonly:
to the declaration of the type parameter, but the type of the Zip function does not match again.
Should we add readonly to all places where this type is used?
No need, can we just remove the readonly modification?
Typescript has a built-in advanced type readonly:
You can add readonly modification to each index of the index type:
But there is no advanced type that removes the readonly modification. We can implement it ourselves:
Use the mapping type syntax to construct a new index type. Adding -readonly means removing the readonly modification.
#Some students may ask, is the array type also an index type?
Yes, the index type is a type that aggregates multiple elements, so objects, arrays, and classes are all.
So we can naturally use it on arrays:
(To be precise, it’s called a tuple. A tuple has a fixed number of elements. Array)
Then we only need to use Mutable to remove readonly before passing in the Zip:
Let’s try again:
Done! Now the return value type is correct.
But there is still a problem. If the literal is not passed in directly, the literal type cannot be deduced. At this time, something seems wrong:
But don’t we all declare overloaded types?
If the literal type cannot be deduced, it should match this:
But in fact it matches the first one:
At this time, you only need to change the order of the two function types:
At this time, the situation of literal parameters is still correct:
Why?
Because the types of overloaded functions are matched from top to bottom, as long as one is matched, it will be applied.
In the case of non-literal values, the type is number[], which can match the type of unknown[], so that function type takes effect.
In the case of literals, the derivation is readonly [1,2,3], with readonly so it does not match unknown[], and continues to match, just The function type with type parameters was matched.
In this way, the appropriate function type is applied in both cases.
The whole code is like this:
type Zip = One extends [
infer OneFirst,
...infer Rest1
]
? Other extends [infer OtherFirst, ...infer Rest2]
? [[OneFirst, OtherFirst], ...Zip]
: []
: [];
type Mutable = {
-readonly [Key in keyof Obj]: Obj[Key];
};
function zip(target: unknown[], source: unknown[]): unknown[];
function zip(
target: Target,
source: Source
): Zip, Mutable>;
function zip(target: unknown[], source: unknown[]) {
if (!target.length || !source.length) return [];
const [one, ...rest1] = target;
const [other, ...rest2] = source;
return [[one, other], ...zip(rest1, rest2)];
}
const result = zip([1, 2, 3] as const, [4, 5, 6] as const);
const arr1 = [1, 2, 3];
const arr2 = [4, '5', 6];
const result2 = zip(arr1, arr2);
The above is the detailed content of Share a good TS interview question (including 3 levels) and see which level you can answer!. For more information, please follow other related articles on the PHP Chinese website!