


Share a good TS interview question (including 3 levels) and see which level you can answer!
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.
function zip(target, source) { if (!target.length || !source.length) return []; const [one, ...rest1] = target; const [other, ...rest2] = source; return [[one, other], ...zip(rest1, rest2)]; }
The result is correct:
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 unknown[], Other extends unknown[]> = One extends [infer OneFirst,...infer Rest1] ? Other extends [infer OtherFirst, ...infer Rest2] ? [[OneFirst, OtherFirst], ...Zip<Rest1, Rest2>] : [] : [];
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 Zip
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 unknown[], Other extends unknown[]> = One extends [ infer OneFirst, ...infer Rest1 ] ? Other extends [infer OtherFirst, ...infer Rest2] ? [[OneFirst, OtherFirst], ...Zip<Rest1, Rest2>] : [] : []; type Mutable<Obj> = { -readonly [Key in keyof Obj]: Obj[Key]; }; function zip(target: unknown[], source: unknown[]): unknown[]; function zip<Target extends readonly unknown[], Source extends readonly unknown[]>( target: Target, source: Source ): Zip<Mutable<Target>, Mutable<Source>>; 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);
总结
今天我们做了一道综合的 ts 面试题,一共有三层:
第一层实现 js 的逻辑,用递归或者循环都能实现。
第二层给函数加上类型,用 function 声明类型和 interface 声明函数类型两种方式,参数和返回值都是 unknown[]。
第三层是用类型编程实现精准的类型提示,这一层需要拿到参数的类型,通过提取元素的类型并构造出新的数组类型返回。还要通过函数重载的方式来声明类型,并且要注意重载类型的声明顺序。
as const 能够让字面量推导出字面量类型,但会带有 readonly 修饰,可以自己写映射类型来去掉这个修饰。
其实这也是我们学习 ts 的顺序,我们先要能把 js 逻辑写出来,然后知道怎么给函数、class 等加 ts 类型,之后学习类型编程,知道怎么动态生成类型。
其中类型编程是 ts 最难的部分,也是最强大的部分。攻克了这一层,ts 就可以说学的差不多了。
【相关推荐:javascript学习教程
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!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



PHP and Vue: a perfect pairing of front-end development tools. In today's era of rapid development of the Internet, front-end development has become increasingly important. As users have higher and higher requirements for the experience of websites and applications, front-end developers need to use more efficient and flexible tools to create responsive and interactive interfaces. As two important technologies in the field of front-end development, PHP and Vue.js can be regarded as perfect tools when paired together. This article will explore the combination of PHP and Vue, as well as detailed code examples to help readers better understand and apply these two

In front-end development interviews, common questions cover a wide range of topics, including HTML/CSS basics, JavaScript basics, frameworks and libraries, project experience, algorithms and data structures, performance optimization, cross-domain requests, front-end engineering, design patterns, and new technologies and trends. . Interviewer questions are designed to assess the candidate's technical skills, project experience, and understanding of industry trends. Therefore, candidates should be fully prepared in these areas to demonstrate their abilities and expertise.

JavaScript tutorial: How to get HTTP status code, specific code examples are required. Preface: In web development, data interaction with the server is often involved. When communicating with the server, we often need to obtain the returned HTTP status code to determine whether the operation is successful, and perform corresponding processing based on different status codes. This article will teach you how to use JavaScript to obtain HTTP status codes and provide some practical code examples. Using XMLHttpRequest

Django is a web application framework written in Python that emphasizes rapid development and clean methods. Although Django is a web framework, to answer the question whether Django is a front-end or a back-end, you need to have a deep understanding of the concepts of front-end and back-end. The front end refers to the interface that users directly interact with, and the back end refers to server-side programs. They interact with data through the HTTP protocol. When the front-end and back-end are separated, the front-end and back-end programs can be developed independently to implement business logic and interactive effects respectively, and data exchange.

As a fast and efficient programming language, Go language is widely popular in the field of back-end development. However, few people associate Go language with front-end development. In fact, using Go language for front-end development can not only improve efficiency, but also bring new horizons to developers. This article will explore the possibility of using the Go language for front-end development and provide specific code examples to help readers better understand this area. In traditional front-end development, JavaScript, HTML, and CSS are often used to build user interfaces

Combination of Golang and front-end technology: To explore how Golang plays a role in the front-end field, specific code examples are needed. With the rapid development of the Internet and mobile applications, front-end technology has become increasingly important. In this field, Golang, as a powerful back-end programming language, can also play an important role. This article will explore how Golang is combined with front-end technology and demonstrate its potential in the front-end field through specific code examples. The role of Golang in the front-end field is as an efficient, concise and easy-to-learn

Introduction to the method of obtaining HTTP status code in JavaScript: In front-end development, we often need to deal with the interaction with the back-end interface, and HTTP status code is a very important part of it. Understanding and obtaining HTTP status codes helps us better handle the data returned by the interface. This article will introduce how to use JavaScript to obtain HTTP status codes and provide specific code examples. 1. What is HTTP status code? HTTP status code means that when the browser initiates a request to the server, the service

Django: A magical framework that can handle both front-end and back-end development! Django is an efficient and scalable web application framework. It is able to support multiple web development models, including MVC and MTV, and can easily develop high-quality web applications. Django not only supports back-end development, but can also quickly build front-end interfaces and achieve flexible view display through template language. Django combines front-end development and back-end development into a seamless integration, so developers don’t have to specialize in learning
