This is related to REST API

Popular New Releases in REST

json-server

fastapi

0.75.2

beego

Release v2.0.2

yapi

修复 沙箱 提权问题

NeteaseCloudMusicApi

v4.5.12

Popular Libraries in REST

public-apis

by public-apis doticonpythondoticon

star image 184682 doticonMIT

A collective list of free APIs

json-server

by typicode doticonjavascriptdoticon

star image 59172 doticonMIT

Get a full fake REST API with zero coding in less than 30 seconds (seriously)

iptv

by iptv-org doticonjavascriptdoticon

star image 49563 doticonUnlicense

Collection of publicly available IPTV channels from all over the world

fastapi

by tiangolo doticonpythondoticon

star image 44054 doticonMIT

FastAPI framework, high performance, easy to learn, fast to code, ready for production

beego

by beego doticongodoticon

star image 28039 doticonNOASSERTION

beego is an open-source, high-performance web framework for the Go programming language.

request

by request doticonjavascriptdoticon

star image 25202 doticonApache-2.0

🏊🏾 Simplified HTTP request client.

yapi

by YMFE doticonjavascriptdoticon

star image 23924 doticonApache-2.0

YApi 是一个可本地部署的、打通前后端及QA的、可视化的接口管理平台

NeteaseCloudMusicApi

by Binaryify doticonjavascriptdoticon

star image 23544 doticonMIT

网易云音乐 Node.js API service

django-rest-framework

by encode doticonpythondoticon

star image 22954 doticonNOASSERTION

Web APIs for Django. 🎸

Trending New libraries in REST

amplication

by amplication doticontypescriptdoticon

star image 7019 doticonApache-2.0

Amplication is an open‑source development tool. It helps you develop quality Node.js applications without spending time on repetitive coding tasks.

trpc

by trpc doticontypescriptdoticon

star image 5188 doticonMIT

🧙‍♀️ End-to-end typesafe APIs made easy

BrasilAPI

by BrasilAPI doticonjavascriptdoticon

star image 4411 doticonMIT

Vamos transformar o Brasil em uma API?

pest

by pestphp doticonphpdoticon

star image 4192 doticonMIT

Pest is an amazing and elegant PHP Testing Framework with a focus on simplicity

go-cqhttp

by Mrs4s doticongodoticon

star image 4085 doticonAGPL-3.0

cqhttp的golang实现,轻量、原生跨平台.

public-api-lists

by public-api-lists doticonpythondoticon

star image 3318 doticonMIT

A collective list of free APIs for use in software and web development 🚀 (Clone of https://github.com/public-apis/public-apis)

xh

by ducaale doticonrustdoticon

star image 2772 doticonMIT

Friendly and fast tool for sending HTTP requests

django-ninja

by vitalik doticonpythondoticon

star image 2769 doticonMIT

💨 Fast, Async-ready, Openapi, type hints based framework for building APIs

encore

by encoredev doticongodoticon

star image 2669 doticonMPL-2.0

Encore is the Go Backend Development Engine helping developers escape the maze of complexity.

Top Authors in REST

1

Esri

66 Libraries

star icon5638

2

googleapis

65 Libraries

star icon36172

3

microsoft

51 Libraries

star icon5355

4

codeforamerica

50 Libraries

star icon482

5

ropensci

42 Libraries

star icon2749

6

mozilla

37 Libraries

star icon4002

7

google

36 Libraries

star icon17415

8

PacktPublishing

34 Libraries

star icon1688

9

SMAKBO

30 Libraries

star icon190

10

Azure

28 Libraries

star icon6785

1

66 Libraries

star icon5638

2

65 Libraries

star icon36172

3

51 Libraries

star icon5355

4

50 Libraries

star icon482

5

42 Libraries

star icon2749

6

37 Libraries

star icon4002

7

36 Libraries

star icon17415

8

34 Libraries

star icon1688

9

30 Libraries

star icon190

10

28 Libraries

star icon6785

Trending Kits in REST

Fetching JSON array data from an API using React can be used in various contexts where you need to retrieve and display data from an external API in a React application. Some examples might include the following:  

  • a dashboard or reporting tool that makes use of a REST API to present data  
  • An application for data visualization or charting that shows current or past data  
  • An application for social networking or messaging that shows user data  
  • a retail or e-commerce website that displays product information or inventory from an API  


You can use the fetch function, a built-in function for making HTTP queries, or a library like Axios to complete the request to fetch data from a JSON array from an API in a React application.  


This pre-written code snippet will show you how to fetch data from a JSON file easily and consume it in your React project.  

Steps-   

  • Declare a state in React to hold API data  
  • To retrieve API data and store the result, use a JS function  
  • On page load, add useEffect to the fetch API  


Here's an example of how you might implement this: 

 

Fig 1: Preview of the output that you will get on running this code from your IDE.

Code

In this solution we're using React and Axios library.

Instructions

Follow the steps carefully to get the output easily.

  1. Install the Node.js and React on your IDE(preferable Visual Studio Code).
  2. Create React Application using npx create-react-app foldername.
  3. cd foldername.
  4. Install npm install axios.
  5. Open the folder in IDE.
  6. Copy the code using "copy" button above and paste it in app.js file(remove the earlier code from app.js).
  7. Import libraries.
  8. Open the terminal from IDE.
  9. npm start to run the file.


You can also refer this url 'DEMO' for getting the above output.

I hope you found this useful. I have added the link to dependent libraries, version information in the following sections.


I found this code snippet by searching for 'display data from jsonplaceholder api using react'in kandi. You can try any such use case!

Environment Tested

I tested this solution in the following versions. Be mindful of changes when working with other versions.

  1. The solution is created in Visual Studio Code 1.73.1.
  2. The solution is tested on node v18.12.1 and npm v8.19.2.
  3. React version-18.2.0.
  4. Axios library version-0.26.1.


Using this solution, we are able to fetch Json array data from API using React with simple steps. This process also facilities an easy way to use, hassle-free method to create a hands-on working version of code which would help us to fetch Json array data from API using React.

Dependent Library

You can also search for any libraries on kandi like 'react' and 'axios'.

Support

  1. For any support on kandi solution kits, please use the chat
  2. For further learning resources, visit the Open Weaver Community learning page.


The Facebook API enables developers to create apps that interact with the Facebook platform and access its data, such as user profiles, posts, and comments. By leveraging these libraries, users can improve their Facebook marketing strategies, collect data for research purposes, and engage with their audience more effectively. 



These libraries are valuable for developers, marketers, and companies that wish to create and deploy Facebook API apps for various objectives such as social media monitoring, influencer marketing, and audience analysis. Users may access and analyze Facebook data in real-time by employing Python Facebook API modules, which can enhance their marketing tactics and audience engagement.  



Here is a list of the 8 Best Python Facebook API Libraries: 

Facebook-SDK 

  • Helps in accessing Facebook data, such as user profiles and posts. 
  • Useful in automating Facebook interactions, such as posting and commenting. 
  • Helps in managing Facebook ads and campaigns. 
  • Useful in building custom Facebook applications. 

statsforecast

  • Helps in forecasting time series data, such as Facebook metrics. 
  • Useful in predicting future trends in Facebook data. 
  • Helps in generating statistical models of Facebook data. 
  • Useful in building custom Facebook analytics tools. 

Fbchat 

  • Helps in automating Facebook Messenger interactions, such as sending and receiving messages. 
  • Useful in building custom Facebook chatbots. 
  • Helps in managing Facebook groups and pages. 
  • Useful in automating Facebook Messenger marketing campaigns. 

Facebook Business SDK 

  • Helps in accessing Facebook data, such as user profiles and posts. 
  • Useful in automating Facebook interactions, such as posting and commenting. 
  • Helps in managing Facebook ads and campaigns. 
  • Useful in building custom Facebook applications. 

Facepy 

  • Helps in accessing Facebook data, such as user profiles and posts. 
  • Useful in automating Facebook interactions, such as posting and commenting. 
  • Helps in managing Facebook ads and campaigns. 
  • Useful in building custom Facebook applications. 

PyFacebook 

  • Helps in accessing Facebook data, such as user profiles and posts. 
  • Useful in automating Facebook interactions, such as posting and commenting. 
  • Helps in managing Facebook ads and campaigns. 
  • Useful in building custom Facebook applications. 

Facepager 

  • Helps in accessing Facebook data, such as user profiles and posts. 
  • Useful in automating Facebook interactions, such as posting and commenting. 
  • Helps in managing Facebook ads and campaigns. 
  • Useful in building custom Facebook applications. 

PySocialWatcher 

  • Helps in monitoring Facebook user activity, such as posts and comments. 
  • Useful in tracking changes to Facebook user profiles. 
  • Helps in collecting Facebook data for research purposes. 
  • Useful in building custom Facebook monitoring tools. 

The Instagram API enables developers to create apps that interact with the Instagram platform and access data such as user profiles, media, and comments. By leveraging these libraries, users can streamline their Instagram marketing strategies, collect data for research purposes, and improve their engagement with their audience. 



These libraries benefit developers, marketers, and businesses who wish to create and deploy Instagram API applications for various objectives such as social media monitoring, influencer marketing, and audience analysis. Users can access and analyze Instagram data in real time by employing Python Instagram API modules, which can help improve marketing strategies and interaction with their audience. 



Here is the list of 8 Best Python Instagram API Libraries: 

Instapy 

  • Helps in automating Instagram interactions, such as liking and commenting. 
  • Useful in scheduling Instagram posts and stories. 
  • Helps in generating statistics about Instagram accounts. 
  • Useful in building Instagram chatbots. 

Instaloader 

  • Helps in downloading Instagram media and metadata. 
  • Useful in archiving Instagram content for later use. 
  • Helps in creating backups of Instagram profiles. 
  • Useful in collecting Instagram data for research purposes. 

python-instagram 

  • Helps in accessing Instagram data, such as user profiles and media. 
  • Useful in automating Instagram interactions, such as following and unfollowing users. 
  • Helps in posting photos and videos to Instagram. 
  • Useful in managing Instagram ads and campaigns. 

InstaLooter 

  • Helps in downloading Instagram media and metadata. 
  • Useful in archiving Instagram content for later use. 
  • Helps in creating backups of Instagram profiles. 
  • Useful in collecting Instagram data for research purposes. 

InstaScrape 

  • Helps in scraping Instagram data, such as user profiles and media. 
  • Useful in extracting insights about Instagram audiences. 
  • Helps in collecting Instagram data for research purposes. 
  • Useful in building custom Instagram crawlers. 

Instabot 

  • Helps in automating Instagram interactions, such as liking, commenting, and following users. 
  • Useful in creating custom Instagram bots for specific purposes. 
  • Helps in building Instagram chatbots. 
  • Useful in scheduling Instagram posts and stories. 

InstaLivecli

  • Helps in streaming live videos from Instagram. 
  • Useful in creating custom Instagram live stream tools. 
  • Helps in monitoring live events on Instagram. 
  • Useful in building Instagram live chatbots. 

BetterCall 

  • Helps in automating Instagram interactions with a graphical user interface. 
  • Useful in scheduling Instagram posts and stories. 
  • Helps in generating statistics about Instagram accounts. 
  • Useful in building Instagram chatbots with a GUI interface. 

Java API gateway is software that accepts an app's user request, diverts it to other backend services, gathers the necessary info, and supplies it to the application user in a single, combined package. It also provides analytics, threat protection layers, and other application security. Java API gateway is a common entry point for all API calls that come into an app, whether hosted on-premises or in the cloud. It receives remote requests and returns the requested data. Consider the web application of a restaurant. Even though all that information is gathered and delivered from various backend microservices or APIs, a user can enter a single request and easily access the: 


  • Restaurant's menu,
  • Diners' photos
  • Reviews
  • Payment service, and
  • A map to check its location using a laptop or cellphone. 


An API gateway receives and processes their request. Developers use microservices in DevOps organizations to build and deploy apps in a fast-paced, iterative manner. API gateways provide three key services between a user and a collection of microservices: request routing, API composition, and protocol translation. In addition to simply servicing requests, an API gateway adds value by making data available in a format appropriate for the requestor's technology. For example, someone using a web browser to request information about a retail store receives far more information than someone using a mobile phone to request and view the same store's data. 

 

APIs are one of the most standard ways for microservices to communicate with one another. As integration and interconnectivity gain importance, APIs are becoming more and more crucial daily for software developers. Furthermore, APIs are used to provision infrastructure in modern cloud development, including the serverless model, and can use Java API gateway to deploy and manage serverless functions. 

 

Several Java API libraries help engineers to reuse code for networking other functionalities of the applications. Some examples of standard libraries are- scalecube-services, service-proxy, kong-java-client, aws-gateway-executor, gateleen, handyman, API-gateway, product-microgateway, shenyu, ship-gate, among others. 


Check out the below list to find the best top 10 Java API gateway libraries for your application development: 

Here are the top python telegram API libraries that any developer can access to simplify the creation and maintenance of telegram bots and other services.   


The messaging service Telegram provides two diverse types of APIs for programmers to use. Using the Bot API, you may quickly make software that uses Telegram messages as an interface. You can create your own uniquely designed Telegram clients using the TDLib and Telegram API. Many uses for the Telegram Bot API are possible, ranging from systems that control notifications to video or image editing. Creating interactive games or providing individualized news updates is an additional potential use for the Telegram Bot API.  


The best Python Telegram API libraries are presented below, precisely categorized, and picked based on reviews and features. 

python-telegram-bot- 

  • Asynchronous interface for telegram bot API. 
  • Featuring high-level classes for easy implementation. 
  • Optional 3rd party dependencies are available.

Telethon- 

  • Interacting with telegram becomes easy with this python library. 
  • It is an MTProto library. 
  • Can also be used with telegram bots. 

pyTelegramBotAPI- 

  • Extensible python API for Telegram bot. 
  • Contains message handlers and makes function names customizable.  
  • It is an HTTP-based interface. 

aiogram- 

  • Written with asyncio and aiohttp. 
  • The framework is completely asynchronous. 
  • The client/server framework is concurrent. 

pyrogram- 

  • Interact with the main telegram API through a user account. 
  • Easy install using pip. 
  • It's asynchronous but can be used synchronously if needed.

telegramscraper- 

  • Many accounts are supported at the same time. 
  • Telegram scrapper and adder. 
  • Scrapping is possible for public groups in bulk. 

pytgcalls- 

  • Exclusive for telegram group calls. 
  • Uses NodeJS’s WebRTC library. 
  • Support Pyrogram and Telethon clients. 

opentele- 

  • For switching between tdata and telethon sessions. 
  • Real data can be used to randomize device info. 
  • Bot detection can be avoided. 

telemirror- 

  • Client API for telegram message forwarding. 
  • Message filters to identify incoming messages. 
  • Mapping of source and target channels.

python-telegram-handler- 

  • Handles logs using telegram bot API. 
  • Easy use with registering and obtaining the authentication token.  
  • If an exception, the handler retrieves chat_id. 

aiotg- 

  • Easy and declarative API. 
  • Hassle-free setup - no need for SSL certificates or static IP. 
  • Built-in support for analytics via chatbase.com. 
  • Automatic handling of Telegram API throttling or timeouts. 

Django Calendar Libraries include Automating customer service, marketing, Creating chatbots, customer feedback, and Automating payments.  


Python WhatsApp API libraries are libraries of code written in the Python programming language that can develop applications that interact with the WhatsApp messaging platform. These libraries typically enable developers to create tools, bots, and other programs to send and receive messages, process messages and integrate with other services and APIs. 


Let us look at these libraries in detail. 

yowsup

  • Supports both the WhatsApp web and mobile platforms.
  • Allows developers to send and receive messages, images, videos, and audio files.
  • Supports group chats and broadcast messages.

whatsapp-framework

  • Offers a powerful text-parsing feature that allows developers to parse incoming messages. 
  • Supports both synchronous and asynchronous messaging.
  • Easy-to-use design helps developers quickly integrate its features into their applications.

PyWhatKit

  • Built-in scheduler allows you to schedule messages to be sent at a later date and time.   
  • Simple, intuitive, and user-friendly API. 
  • Possible to read incoming messages and respond to them.

PyWhatsapp

  • Offers a built-in event loop, which allows users to process incoming messages and react to them in real time.
  • Highly flexible and can be used to create powerful custom WhatsApp bots.
  • Supports media sending, which is unavailable in most other Python WhatsApp API libraries. 

whatsapp-cli

  • Command-line interface (CLI) tool allows users to interact directly with the WhatsApp API from their terminal.  
  • Many advanced features include group chats, file sharing, broadcast messages, and more.  
  • Built using the WhatsApp Web API, it is always up-to-date with the latest WhatsApp features. 

whatsapp-api-client-python

  • An automated setup process that makes it easy to get up and run quickly with the WhatsApp API.   
  • Supports both Python 2 and Python 3. 
  • Built-in error handling.

WhatsApp-Chat-Analyzer-API

  • Used to generate visualizations of the conversations, such as word clouds, heatmaps, and network graphs.
  • Provides a range of features for analyzing conversations, such as sentiment analysis, keyword extraction, and topic modeling.
  • Open source and is available for free.

whatsapp-wrapper

  • Provides a wrapper for the official WhatsApp API.
  • Built-in webhook system.
  • Provides robust API endpoints for creating, editing, and deleting conversations.

pywassap

  • Offers a complete suite of APIs to interact with WhatsApp services.
  • Highly customizable, allowing users to adjust the API to their specific needs.
  • Offers a secure and reliable connection with WhatsApp’s servers.

Chat-API

  • Automated message scheduling.
  • File and media messaging.
  • Easy integration with other apps and services.

FAQ  

What is WhatsApp Cloud API Python?  

WhatsApp API doesn’t directly interact with a “Cloud API” as other services do. It is typically hosted on the business’s servers. It allows them to send and receive messages through WhatsApp.   

  

What is the WhatsApp Business API?  

WhatsApp provides a Business API. It allows businesses API to provide a way for businesses to send messages to users. It helps receive messages from users and manage various aspects of business accounts.  


WhatsApp Business API supports various programming languages, including Python. It allows developers to integrate WhatsApp messaging capabilities into their applications.   

  

Is there a Python wrapper for WhatsApp?  

WhatsApp is restrictive about third-party applications. It helps in interacting with their service to maintain user privacy and security. However, there have been community-driven projects and third-party libraries. It provides Python wrappers or APIs to interact with WhatsApp.  


These might have limitations and may not be officially endorsed. However, it is crucial to be cautious when using such tools. It helps ensure compliance with WhatsApp’s terms of service.  

  

What are the different types of WhatsApp messages?  

WhatsApp supports various WhatsApp message types. It facilitates different forms of communication. Here are some common types of messages you can send and receive on WhatsApp:  

  • Text Messages  
  • Images and Videos  
  • Location Sharing  
  • Voice Messages  
  • Documents  
  • Stickers and Emojis  
  • Contacts  
  • Status Updates  
  • Reply and Quoted Messages  
  • GIFs  
  • Group Messages 

When it comes to honeymoon packages, Kerala has earned its reputation as one of the most romantic destinations in the world. Amidst the various jewels that adorn this beautiful state, the Athirapilly Waterfalls stand out as an enchanting and crucial component of Kerala's tourism, especially for honeymooners. Let's delve into the importance of Athirapilly Waterfalls in the tourism map of Kerala honeymoon packages.


Setting the Romantic Tone

Athirapilly Waterfalls, often referred to as the "Niagara Falls of India," are renowned for their breathtaking beauty and serene ambiance. The cascading waters, lush green surroundings, and the soothing sound of the falls create a romantic atmosphere that is unparalleled. For honeymooners, this natural wonder sets the perfect tone for a romantic getaway.


Captivating Backdrop for Memories

The falls provide an awe-inspiring backdrop for capturing those precious honeymoon moments. Newlyweds can have their photographs taken against the backdrop of the falls, creating memories that will last a lifetime. The beauty of Athirapilly Waterfalls enhances the charm of honeymoon photographs, making them even more special.


Secluded Retreats

Several resorts and accommodations are situated in the vicinity of Athirapilly, offering honeymooners secluded and romantic retreats. These resorts often have rooms or cottages with stunning views of the waterfalls, allowing couples to enjoy the beauty and serenity of Athirapilly right from their doorstep.


Adventure and Bonding

Honeymoons are not just about relaxation; they are also about bonding and creating shared experiences. Athirapilly offers adventurous opportunities like trekking and nature walks through the surrounding rainforests. Couples can explore the lush greenery hand in hand, strengthening their bond amidst the wonders of nature.


Monsoon Magic

The monsoon season transforms Athirapilly Waterfalls into a mesmerizing spectacle. The falls are at their fullest during this time, and the entire region comes alive with vibrant greenery. Honeymooners who visit Athirapilly during the monsoons are treated to a romantic experience like no other, with the falls in their full glory and the aroma of wet earth in the air.


Nearby Attractions

Athirapilly's strategic location makes it a gateway to other romantic destinations in Kerala. The nearby Vazhachal Waterfalls, scenic viewpoints, and the Athirapilly-Vazhachal region's natural beauty provide couples with a variety of options for exploration and romantic escapades.


Serenity and Privacy

Unlike some bustling tourist destinations, Athirapilly offers honeymooners a sense of seclusion and privacy. The falls are surrounded by lush forests, and the relatively lower tourist footfall ensures that couples can enjoy peaceful moments together, undisturbed by crowds.


Local Culture and Cuisine

Honeymoon packages in Kerala often include experiences that introduce couples to the local culture and cuisine. Athirapilly allows honeymooners to savor traditional Kerala dishes while enjoying the serene backdrop of the falls. Engaging with the warm and hospitable locals adds a touch of authenticity to the overall experience.


Sustainable Tourism

Athirapilly is also a hub for eco-tourism, emphasizing the importance of responsible and sustainable tourism. Honeymooners who are environmentally conscious can appreciate the efforts to preserve this natural wonder, making their trip not only romantic but also responsible.

In conclusion, Athirapilly Waterfalls plays a pivotal role in the tourism map of Kerala's honeymoon packages. Its romantic allure, captivating natural beauty, and serene ambiance make it a must-visit destination for couples seeking a romantic and memorable getaway. Athirapilly not only provides a scenic backdrop for love but also offers a range of experiences that allow newlyweds to connect, create memories, and embark on a journey of love that begins with the enchantment of these magnificent falls. It's no wonder that Athirapilly Waterfalls has become an essential stop for honeymooners on their journey through Kerala's romantic landscape.


Best Time To Visit Athirapilly waterfalls


The best time to visit Athirapilly Waterfalls is during the post-monsoon and winter months, which generally span from September to February. This period offers the most favorable weather and the most captivating views of the falls. Here's a breakdown of the seasons and their suitability for visiting Athirapilly:


Post-Monsoon (September to November): This is an excellent time to visit Athirapilly as the monsoon rains have receded, leaving the surroundings lush and green. The waterfalls are at their fullest during this time, creating a mesmerizing spectacle. The weather is relatively cool, making it ideal for outdoor activities like trekking and exploring the nearby forests.


Winter (December to February): The winter months are also an excellent time to visit Athirapilly. The weather is pleasantly cool and dry, and the waterfalls maintain a good flow. This is a popular time for tourists, especially honeymooners, as the romantic ambiance is at its peak. Clear skies and comfortable temperatures make it an ideal time for sightseeing and outdoor adventures.


Pre-Monsoon (March to May): While the weather is generally warm during this period, visiting Athirapilly in the pre-monsoon season is still possible. The falls may have slightly lower water levels compared to post-monsoon, but the lush greenery and the surrounding flora are still beautiful. If you can handle the warmth, you can enjoy the serene ambiance with fewer crowds.


Monsoon (June to August): The monsoon season in Kerala, including Athirapilly, is characterized by heavy rainfall. While the falls are at their most spectacular during this time, with a torrential flow of water, it's not the safest or most comfortable time to visit. Landslides and flooding can occur, making it a less suitable period for travel and outdoor activities.


Keep in mind that weather patterns can vary from year to year, so it's a good idea to check the current weather conditions and forecasts before planning your trip. Ultimately, the best time to visit Athirapilly Waterfalls depends on your preferences, whether you prefer the lush greenery and full waterfalls of the post-monsoon and winter months or are willing to experience the dramatic monsoon season, albeit with certain risks and challenges.

In today's globalized world, proficiency in the English language is not just an advantage but often a necessity for individuals seeking higher education opportunities or international career prospects. Likewise, excelling in subjects like physics, chemistry, and mathematics is crucial for academic success. Tuto Training Center UAE, with its commitment to providing top-notch IELTS training and private tutoring services in these subjects, has emerged as a beacon of academic excellence in Dubai and Abu Dhabi.Private Home Tutor In Dubai Abu Dhabi Al Ain


Addressing Your Educational Needs


Tuto Training Center UAE boasts two convenient locations, ensuring that learners across the United Arab Emirates have easy access to their exceptional services. In Dubai, you can find them at M 102, Al Hilal Bank Building, near Al Tawar Centre, Al Qusais-2. Meanwhile, in Abu Dhabi, they are situated at Opal House Building, Al Mamoura Area, Office No. 702. These strategically placed centers make it convenient for students in both cities to benefit from their expertise. Physics Private Tutors In Dubai Abu Dhabi Al Ain


A Phone Call Away


For inquiries, scheduling, or any assistance you may require, you can reach Tuto Training Center UAE via phone at +9715-640-640-55. Their dedicated team is always ready to answer your questions and guide you through the process of enrolling in their courses or arranging private tutoring sessions. Chemistry Private Tutors In Dubai Abu Dhabi Al Ain


Unlocking Your Potential


Tuto Training Center UAE understands the diverse educational needs of students, which is why they offer a wide range of services, including:


Best IELTS Training in Dubai: Mastering the IELTS exam is essential for those planning to study or work abroad. Tuto Training Center UAE's IELTS training program equips students with the language skills needed to excel in the test. Their experienced instructors provide comprehensive guidance, ensuring that students are well-prepared to achieve their desired band scores.


Private Home Tutor in Dubai, Abu Dhabi, Al Ain: For students seeking one-on-one attention and customized learning experiences, Tuto Training Center UAE offers private tutoring services. Their expert tutors specialize in subjects like physics, chemistry, and mathematics, catering to the unique needs of each student. Whether you need assistance with complex mathematical concepts or a deeper understanding of chemical reactions, their tutors are here to help you succeed. Maths Private Tutors In Dubai Abu Dhabi Al Ain


Physics, Chemistry, and Maths Private Tutors in Dubai, Abu Dhabi, Al Ain: The subjects of physics, chemistry, and mathematics can pose challenges to many students. Tuto Training Center UAE's team of dedicated and knowledgeable tutors is well-equipped to simplify these subjects, making them more accessible and enjoyable for learners.



Tuto Training Center UAE is more than just an educational institution; it is a partner in your academic journey. Their commitment to providing exceptional IELTS training and expert private tutoring services in physics, chemistry, and mathematics sets them apart as a trusted source of academic support in Dubai and Abu Dhabi.


If you aspire to excel in the IELTS exam or need expert guidance in the subjects of physics, chemistry, or mathematics, Tuto Training Center UAE, with its highly qualified tutors and convenient locations, is the ideal choice for unlocking your full potential. Contact them today at info@tutotraining.ae to embark on your path to academic success.

Trending Discussions on REST

How to redirect in React Router v6?

Is every "complete" object a "most-derived" object?

Filter out everything before a condition is met, keep all elements after

"Configuring the trigger failed, edit and save the pipeline again" with no noticeable error and no further details

Multiple labels per item on Kendo chart

Python 3.10 pattern matching (PEP 634) - wildcard in string

Redirect in react-router-dom V6

Patch request not patching - 403 returned - django rest framework

Haskell: Can I read integers directly into an array?

Typescript: deep keyof of a nested object, with related type

QUESTION

How to redirect in React Router v6?

Asked 2022-Mar-24 at 17:22

I am trying to upgrade to React Router v6 (react-router-dom 6.0.1).

Here is my updated code:

1import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
2
3<BrowserRouter>
4  <Routes>
5    <Route path="/" element={<Home />} />
6    <Route path="/lab" element={<Lab />} />
7    <Route render={() => <Navigate to="/" />} />
8  </Routes>
9</BrowserRouter>
10

The last Route is redirecting the rest of paths to /.

However, I got an error

TS2322: Type '{ render: () => Element; }' is not assignable to type 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)'.   Property 'render' does not exist on type 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)'.

However, based on the doc, it does have render for Route. How to use it correctly?

ANSWER

Answered 2022-Mar-18 at 18:41

I think you should use the no match route approach.

Check this in the documentation.

https://reactrouter.com/docs/en/v6/getting-started/tutorial#adding-a-no-match-route

1import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
2
3<BrowserRouter>
4  <Routes>
5    <Route path="/" element={<Home />} />
6    <Route path="/lab" element={<Lab />} />
7    <Route render={() => <Navigate to="/" />} />
8  </Routes>
9</BrowserRouter>
10import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
11
12<BrowserRouter>
13  <Routes>
14    <Route path="/" element={<Home />} />
15    <Route path="/lab" element={<Lab />} />
16    <Route
17        path="*"
18        element={<Navigate to="/" replace />}
19    />
20  </Routes>
21</BrowserRouter>
22
Update - 18/03/2022

To keep the history clean, you should set replace prop. This will avoid extra redirects after the user click back. Thanks @Paul for this tip.

Source https://stackoverflow.com/questions/69868956

QUESTION

Is every "complete" object a "most-derived" object?

Asked 2022-Mar-21 at 02:30

Per [intro.object]/2:

[..] An object that is not a subobject of any other object is called a complete object [..].

So consider this snippet of code:

1struct Base {};
2struct Derived : Base {};
3struct MostDerived : Derived {};
4

I can't understand the wording in this quote from the standard:

[object.intro]/6:

If a complete object, a member subobject, or an array element is of class type, its type is considered the most derived class [..] An object of a most derived class type or of a non-class type is called a most derived object.

From the quote what I understand is that a type of a complete object is of "most-derived" class type. I stopped here, I really do not understand the rest of the wording.

  • Per the question "What does the "most derived object" mean?" I think that (correct me if I am wrong), objects of type "most-derived" class only, like MostDerived, are called "most-derived" objects. Is this true?

  • If I have created an object of Base like this: Base b_obj = Base(), is the object b_obj a "most-derived" object?

  • If I have created an object of Derived like this: Derived d_obj = Derived(), is the object d_obj also a "most-derived" object?

  • Does the word "derived" in "most-derived" mean that the object is an object of a class like MostDerived, or mean that the object has no class subobject in it?

ANSWER

Answered 2022-Mar-21 at 00:32
  1. An object is not a class.
  2. An object is an instantiation of a class, an array, or built-in-type.
  3. Subobjects are class member objects, array elements, or base classes of an object.
  4. Derived objects (and most-derived objects) only make sense in the context of class inheritance.
1struct Base {};
2struct Derived : Base {};
3struct MostDerived : Derived {};
4void foo() {
5    int i = 0; // complete object, but not most-derived (not class type)
6}
7
8class A {
9   int i = 0; // non complete object, not most-derived
10}
11
12void bar() {
13    A a; // complete object, but not derived, so can't be "most derived"
14}
15
16class B : A { }
17
18void biz() {
19   B b; // complete object, derived object, and most-derived object
20}
21

Is every "complete" object is "most-derived" object

No. A most-derived object is an object of a most-derived class, and a most-derived class must be of a class type. Objects may be of class type, but non-class type objects also exist.

  • Every complete object of class-type is a most-derived object only if that class inherits.
  • A most-derived object may be a subobject, so you cannot infer object completeness from most-derivedness (however, you can infer that the most-derived object is of class type).

So if I have created an object of Base like this: Base b_obj = Base(), Is the object b_obj is "most-derived" object?

Yes. The most-derived object of b_obj is an object of type Base. This is not necessarily a complete object, however, since this could be a class member definition. Again, complete is not synonymous with most-derived.


Also if I have created an object of Derived like this: Derived d_obj = Derived(), Is the object d_obj is also a "most-derived" object?

Yes. The most-derived object of d_obj is an object of type Derived.


If you have an object created as type MostDerived:

1struct Base {};
2struct Derived : Base {};
3struct MostDerived : Derived {};
4void foo() {
5    int i = 0; // complete object, but not most-derived (not class type)
6}
7
8class A {
9   int i = 0; // non complete object, not most-derived
10}
11
12void bar() {
13    A a; // complete object, but not derived, so can't be "most derived"
14}
15
16class B : A { }
17
18void biz() {
19   B b; // complete object, derived object, and most-derived object
20}
21MostDerived md;
22
  • It is an object of type MostDerived
  • It is an object of type Derived
  • It is an object of type Base
  • If it is not a member subobject, then it is a complete object
  • Its most-derived object is of type MostDerived
  • It has a subobject of type Derived, which is neither a complete object nor a most-derived object
  • Its subobject of type Derived has a subobject of type Base, which is neither a complete object nor a most-derived object.

Source https://stackoverflow.com/questions/71551522

QUESTION

Filter out everything before a condition is met, keep all elements after

Asked 2022-Feb-23 at 21:32

I was wondering if there was an easy solution to the the following problem. The problem here is that I want to keep every element occurring inside this list after the initial condition is true. The condition here being that I want to remove everything before the condition that a value is greater than 18 is true, but keep everything after. Example

Input:

1p = [4,9,10,4,20,13,29,3,39]
2

Expected output:

1p = [4,9,10,4,20,13,29,3,39]
2p = [20,13,29,3,39]
3

I know that you can filter over the entire list through

1p = [4,9,10,4,20,13,29,3,39]
2p = [20,13,29,3,39]
3[x for x in p if x>18] 
4

But I want to stop this operation once the first value above 18 is found, and then include the rest of the values regardless if they satisfy the condition or not. It seems like an easy problem but I haven't found the solution to it yet.

ANSWER

Answered 2022-Feb-05 at 19:59

You can use itertools.dropwhile:

1p = [4,9,10,4,20,13,29,3,39]
2p = [20,13,29,3,39]
3[x for x in p if x>18] 
4from itertools import dropwhile
5
6p = [4,9,10,4,20,13,29,3,39]
7
8p = dropwhile(lambda x: x <= 18, p)
9print(*p) # 20 13 29 3 39
10

In my opinion, this is arguably the easiest-to-read version. This also corresponds to a common pattern in other functional programming languages, such as dropWhile (<=18) p in Haskell and p.dropWhile(_ <= 18) in Scala.


Alternatively, using walrus operator (only available in python 3.8+):

1p = [4,9,10,4,20,13,29,3,39]
2p = [20,13,29,3,39]
3[x for x in p if x&gt;18] 
4from itertools import dropwhile
5
6p = [4,9,10,4,20,13,29,3,39]
7
8p = dropwhile(lambda x: x &lt;= 18, p)
9print(*p) # 20 13 29 3 39
10exceeded = False
11p = [x for x in p if (exceeded := exceeded or x &gt; 18)]
12print(p) # [20, 13, 29, 3, 39]
13

But my guess is that some people don't like this style. In that case, one can do an explicit for loop (ilkkachu's suggestion):

1p = [4,9,10,4,20,13,29,3,39]
2p = [20,13,29,3,39]
3[x for x in p if x&gt;18] 
4from itertools import dropwhile
5
6p = [4,9,10,4,20,13,29,3,39]
7
8p = dropwhile(lambda x: x &lt;= 18, p)
9print(*p) # 20 13 29 3 39
10exceeded = False
11p = [x for x in p if (exceeded := exceeded or x &gt; 18)]
12print(p) # [20, 13, 29, 3, 39]
13for i, x in enumerate(p):
14    if x &gt; 18:
15        output = p[i:]
16        break
17else:
18    output = [] # alternatively just put output = [] before for
19

Source https://stackoverflow.com/questions/70964954

QUESTION

&quot;Configuring the trigger failed, edit and save the pipeline again&quot; with no noticeable error and no further details

Asked 2022-Feb-16 at 10:33

I have run in to an odd problem after converting a bunch of my YAML pipelines to use templates for holding job logic as well as for defining my pipeline variables. The pipelines run perfectly fine, however I get a "Some recent issues detected related to pipeline trigger." warning at the top of the pipeline summary page and viewing details only states: "Configuring the trigger failed, edit and save the pipeline again."

The odd part here is that the pipeline works completely fine, including triggers. Nothing is broken and no further details are given about the supposed issue. I currently have YAML triggers overridden for the pipeline, but I did also define the same trigger in the YAML to see if that would help (it did not).

I'm looking for any ideas on what might be causing this or how I might be able to further troubleshoot it given the complete lack of detail that the error/warning provides. It's causing a lot of confusion among developers who think there might be a problem with their builds as a result of the warning.

Here is the main pipeline. the build repository is a shared repository for holding code that is used across multiple repos in the build system. dev.yaml contains dev environment specific variable values. Shared holds conditionally set variables based on the branch the pipeline is running on.

1name: ProductName_$(BranchNameLower)_dev_$(MajorVersion)_$(MinorVersion)_$(BuildVersion)_$(Build.BuildId)
2resources:
3  repositories:
4    - repository: self
5    - repository: build
6      type: git
7      name: Build
8      ref: master
9
10# This trigger isn't used yet, but we want it defined for later.
11trigger: 
12  batch: true
13  branches:
14    include: 
15    - 'dev'
16
17variables:
18- template: YAML/variables/shared.yaml@build
19- template: YAML/variables/dev.yaml@build
20
21jobs:
22- template: ProductNameDevJob.yaml
23  parameters:
24    pipelinePool: ${{ variables.PipelinePool }}
25    validRef: ${{ variables.ValidRef }}
26

Then this is the start of the actual job yaml. It provides a reusable definition of the job that can be used in more than one over-arching pipeline:

1name: ProductName_$(BranchNameLower)_dev_$(MajorVersion)_$(MinorVersion)_$(BuildVersion)_$(Build.BuildId)
2resources:
3  repositories:
4    - repository: self
5    - repository: build
6      type: git
7      name: Build
8      ref: master
9
10# This trigger isn't used yet, but we want it defined for later.
11trigger: 
12  batch: true
13  branches:
14    include: 
15    - 'dev'
16
17variables:
18- template: YAML/variables/shared.yaml@build
19- template: YAML/variables/dev.yaml@build
20
21jobs:
22- template: ProductNameDevJob.yaml
23  parameters:
24    pipelinePool: ${{ variables.PipelinePool }}
25    validRef: ${{ variables.ValidRef }}
26parameters:
27- name: dependsOn
28  type: object
29  default: {}
30- name: pipelinePool
31  default: ''
32- name: validRef
33  default: ''
34- name: noCI
35  type: boolean
36  default: false
37- name: updateBeforeRun
38  type: boolean
39  default: false
40
41jobs:
42- job: Build_ProductName
43  displayName: 'Build ProductName'
44  pool:
45    name: ${{ parameters.pipelinePool }}
46    demands: 
47    - msbuild
48    - visualstudio
49  dependsOn: 
50  - ${{ each dependsOnThis in parameters.dependsOn }}:
51    - ${{ dependsOnThis }}
52  condition: and(succeeded(), eq(variables['Build.SourceBranch'], variables['ValidRef']))
53
54  steps:
55**step logic here
56

Finally, we have the variable YAML which conditionally sets pipeline variables based on what we are building:

1name: ProductName_$(BranchNameLower)_dev_$(MajorVersion)_$(MinorVersion)_$(BuildVersion)_$(Build.BuildId)
2resources:
3  repositories:
4    - repository: self
5    - repository: build
6      type: git
7      name: Build
8      ref: master
9
10# This trigger isn't used yet, but we want it defined for later.
11trigger: 
12  batch: true
13  branches:
14    include: 
15    - 'dev'
16
17variables:
18- template: YAML/variables/shared.yaml@build
19- template: YAML/variables/dev.yaml@build
20
21jobs:
22- template: ProductNameDevJob.yaml
23  parameters:
24    pipelinePool: ${{ variables.PipelinePool }}
25    validRef: ${{ variables.ValidRef }}
26parameters:
27- name: dependsOn
28  type: object
29  default: {}
30- name: pipelinePool
31  default: ''
32- name: validRef
33  default: ''
34- name: noCI
35  type: boolean
36  default: false
37- name: updateBeforeRun
38  type: boolean
39  default: false
40
41jobs:
42- job: Build_ProductName
43  displayName: 'Build ProductName'
44  pool:
45    name: ${{ parameters.pipelinePool }}
46    demands: 
47    - msbuild
48    - visualstudio
49  dependsOn: 
50  - ${{ each dependsOnThis in parameters.dependsOn }}:
51    - ${{ dependsOnThis }}
52  condition: and(succeeded(), eq(variables['Build.SourceBranch'], variables['ValidRef']))
53
54  steps:
55**step logic here
56variables:
57- ${{ if or(eq(variables['Build.SourceBranch'], 'refs/heads/dev'), eq(variables['Build.SourceBranch'], 'refs/heads/users/ahenderson/azure_devops_build')) }}:
58  - name: BranchName
59    value: Dev
60** Continue with rest of pipeline variables and settings of each value for each different context.
61

ANSWER

Answered 2021-Aug-17 at 14:58

I think I may have figured out the problem. It appears that this is related to the use of conditionals in the variable setup. While the variables will be set in any valid trigger configuration, it appears that the proper values are not used during validation and that may have been causing the problem. Switching my conditional variables to first set a default value and then replace the value conditionally seems to have fixed the problem.

It would be nice if Microsoft would give a more useful error message here, something to the extent of the values not being found for a given variable, but adding defaults does seem to have fixed the problem.

Source https://stackoverflow.com/questions/68819306

QUESTION

Multiple labels per item on Kendo chart

Asked 2022-Jan-02 at 21:14

I'm trying to get multiple label per item on Kendo Column chart Desired layout looks like this desired chart

I was able to get only this layout

1import { Component } from '@angular/core';
2import { groupBy, GroupResult } from '@progress/kendo-data-query';
3import { ValueAxisLabels } from '@progress/kendo-angular-charts';
4
5export type TrendItem = {
6  clientName: string;
7  periodName: string;
8  income: number;
9};
10
11@Component({
12  selector: 'my-app',
13  template: `
14        &lt;kendo-chart&gt;
15          &lt;kendo-chart-category-axis&gt;
16              &lt;kendo-chart-category-axis-item [categories]=&quot;categories&quot;&gt;
17              &lt;/kendo-chart-category-axis-item&gt;
18          &lt;/kendo-chart-category-axis&gt;
19
20          &lt;kendo-chart-value-axis&gt;
21              &lt;kendo-chart-value-axis-item [labels]=&quot;valueAxisLabels&quot;&gt;
22              &lt;/kendo-chart-value-axis-item&gt;
23          &lt;/kendo-chart-value-axis&gt;
24
25          &lt;kendo-chart-series&gt;
26            &lt;kendo-chart-series-item *ngFor=&quot;let groupedResult of groupedTrendsByPeriod&quot; [data]=&quot;groupedResult.items&quot; field=&quot;income&quot; type=&quot;column&quot;&gt;
27              &lt;kendo-chart-series-item-labels [content]=&quot;labelVisual&quot;&gt;
28              &lt;/kendo-chart-series-item-labels&gt;
29           &lt;/kendo-chart-series-item&gt;
30          &lt;/kendo-chart-series&gt;
31        &lt;/kendo-chart&gt;
32    `,
33})
34export class AppComponent {
35  public valueAxisLabels: ValueAxisLabels = {
36    font: 'bold 16px Arial, sans-serif',
37  };
38
39  public trendItems: TrendItem[] = [
40    {
41      clientName: 'Client1',
42      periodName: 'Q1 2020',
43      income: 20,
44    },
45    {
46      clientName: 'Client1',
47      periodName: 'Q2 2020',
48      income: 15,
49    },
50    {
51      clientName: 'Client1',
52      periodName: 'Q3 2020',
53      income: 35,
54    },
55    {
56      clientName: 'Client1',
57      periodName: 'Q4 2020',
58      income: 40,
59    },
60    {
61      clientName: 'Client2',
62      periodName: 'Q1 2020',
63      income: 15,
64    },
65    {
66      clientName: 'Client2',
67      periodName: 'Q2 2020',
68      income: 20,
69    },
70    {
71      clientName: 'Client2',
72      periodName: 'Q3 2020',
73      income: 15,
74    },
75    {
76      clientName: 'Client2',
77      periodName: 'Q4 2020',
78      income: 30,
79    }
80  ];
81
82  public categories = (groupBy(this.trendItems, [{ field: 'clientName' }]) as GroupResult[])
83    .map((e) =&gt; e.value);
84
85  public groupedTrendsByPeriod = groupBy(this.trendItems, [{ field: 'periodName' }]) as GroupResult[];
86
87  public labelVisual(e: { dataItem: TrendItem }) {
88    return `$${e.dataItem.income}\r\n${e.dataItem.periodName}`;
89  }
90}
91

You can try this code here.

My current result look like this current progress


So my question is how to display multiple labels per item like on the first picture?


My current obstacles.

  • I didn't find a way to add multiple <kendo-chart-series-item-labels> elements. Only one will be rendered, rest will be ignored.
  • I didn't find a way to position labels below column chart. For column chart it's only possible to use "center", "insideBase", "insideEnd", "outsideEnd" options (according to API Reference) but none of them gives me desired position.

ANSWER

Answered 2022-Jan-02 at 08:18

I don't think kendo provides any native solution for that but what I can suggest is to:

  1. Use legends to display each bar meaning. like the example here.

  2. Use some self generated labels and position them under the table which is risky for UI. I provided an example here.

Source https://stackoverflow.com/questions/70465893

QUESTION

Python 3.10 pattern matching (PEP 634) - wildcard in string

Asked 2021-Dec-17 at 10:43

I got a large list of JSON objects that I want to parse depending on the start of one of the keys, and just wildcard the rest. A lot of the keys are similar, like "matchme-foo" and "matchme-bar". There is a builtin wildcard, but it is only used for whole values, kinda like an else.

I might be overlooking something but I can't find a solution anywhere in the proposal:

https://docs.python.org/3/whatsnew/3.10.html#pep-634-structural-pattern-matching

Also a bit more about it in PEP-636:

https://www.python.org/dev/peps/pep-0636/#going-to-the-cloud-mappings

My data looks like this:

1data = [{
2          &quot;id&quot;     : &quot;matchme-foo&quot;,
3          &quot;message&quot;: &quot;hallo this is a message&quot;,
4      },{
5          &quot;id&quot;     : &quot;matchme-bar&quot;,
6          &quot;message&quot;: &quot;goodbye&quot;,
7      },{
8          &quot;id&quot;     : &quot;anotherid&quot;,
9          &quot;message&quot;: &quot;completely diffrent event&quot;
10      }, ...]
11

I want to do something that can match the id without having to make a long list of |'s.

Something like this:

1data = [{
2          &quot;id&quot;     : &quot;matchme-foo&quot;,
3          &quot;message&quot;: &quot;hallo this is a message&quot;,
4      },{
5          &quot;id&quot;     : &quot;matchme-bar&quot;,
6          &quot;message&quot;: &quot;goodbye&quot;,
7      },{
8          &quot;id&quot;     : &quot;anotherid&quot;,
9          &quot;message&quot;: &quot;completely diffrent event&quot;
10      }, ...]
11for event in data:
12    match event:
13        case {'id':'matchme-*'}: # Match all 'matchme-' no matter what comes next
14            log.INFO(event['message'])
15        case {'id':'anotherid'}:
16            log.ERROR(event['message'])
17

It's a relatively new addition to Python so there aren't many guides on how to use it yet.

ANSWER

Answered 2021-Dec-17 at 10:43

You can use a guard:

1data = [{
2          &quot;id&quot;     : &quot;matchme-foo&quot;,
3          &quot;message&quot;: &quot;hallo this is a message&quot;,
4      },{
5          &quot;id&quot;     : &quot;matchme-bar&quot;,
6          &quot;message&quot;: &quot;goodbye&quot;,
7      },{
8          &quot;id&quot;     : &quot;anotherid&quot;,
9          &quot;message&quot;: &quot;completely diffrent event&quot;
10      }, ...]
11for event in data:
12    match event:
13        case {'id':'matchme-*'}: # Match all 'matchme-' no matter what comes next
14            log.INFO(event['message'])
15        case {'id':'anotherid'}:
16            log.ERROR(event['message'])
17for event in data:
18    match event:
19        case {'id': x} if x.startswith(&quot;matchme&quot;): # guard
20            print(event[&quot;message&quot;])
21        case {'id':'anotherid'}:
22            print(event[&quot;message&quot;])
23

Quoting from the official documentation,

Guard

We can add an if clause to a pattern, known as a “guard”. If the guard is false, match goes on to try the next case block. Note that value capture happens before the guard is evaluated:

1data = [{
2          &quot;id&quot;     : &quot;matchme-foo&quot;,
3          &quot;message&quot;: &quot;hallo this is a message&quot;,
4      },{
5          &quot;id&quot;     : &quot;matchme-bar&quot;,
6          &quot;message&quot;: &quot;goodbye&quot;,
7      },{
8          &quot;id&quot;     : &quot;anotherid&quot;,
9          &quot;message&quot;: &quot;completely diffrent event&quot;
10      }, ...]
11for event in data:
12    match event:
13        case {'id':'matchme-*'}: # Match all 'matchme-' no matter what comes next
14            log.INFO(event['message'])
15        case {'id':'anotherid'}:
16            log.ERROR(event['message'])
17for event in data:
18    match event:
19        case {'id': x} if x.startswith(&quot;matchme&quot;): # guard
20            print(event[&quot;message&quot;])
21        case {'id':'anotherid'}:
22            print(event[&quot;message&quot;])
23match point:
24     case Point(x, y) if x == y:
25         print(f&quot;The point is located on the diagonal Y=X at {x}.&quot;)
26     case Point(x, y):
27         print(f&quot;Point is not on the diagonal.&quot;)
28

Source https://stackoverflow.com/questions/70111401

QUESTION

Redirect in react-router-dom V6

Asked 2021-Dec-15 at 05:41

I need to navigate back to the original requested URL after login.

For example, user enters www.example.com/settings as user is not authenticated, it will navigate to login page www.example.com/login.

Once authenticated, it should navigate back to www.example.com/settings automatically.

My original approach with react-router-dom v5 is quite simple:

1const PrivateRoute = ({ isLoggedIn, component: Component, ...rest }) =&gt; {
2  return (
3    &lt;Route
4      {...rest}
5      render={(props) =&gt;
6        isLoggedIn? (
7          &lt;Component {...props} /&gt;
8        ) : (
9          &lt;Redirect
10            to={{ pathname: `/login/${props.location.search}`, state: { from: props.location } }}
11          /&gt;
12        )
13      }
14    /&gt;
15  );
16};
17
18
19&lt;PrivateRoute exact isLoggedIn={isLoggedIn} path=&quot;/settings&quot; component={Settings} /&gt;
20
21

Can some one tell me how to do that in v6? Thanks in advance

ANSWER

Answered 2021-Dec-15 at 05:41

In react-router-dom v6 rendering routes and handling redirects is quite different than in v5. Gone are custom route components, they are replaced with a wrapper component pattern.

v5 - Custom Route

Takes props and conditionally renders a Route component with the route props passed through or a Redirect component with route state holding the current location.

1const PrivateRoute = ({ isLoggedIn, component: Component, ...rest }) =&gt; {
2  return (
3    &lt;Route
4      {...rest}
5      render={(props) =&gt;
6        isLoggedIn? (
7          &lt;Component {...props} /&gt;
8        ) : (
9          &lt;Redirect
10            to={{ pathname: `/login/${props.location.search}`, state: { from: props.location } }}
11          /&gt;
12        )
13      }
14    /&gt;
15  );
16};
17
18
19&lt;PrivateRoute exact isLoggedIn={isLoggedIn} path=&quot;/settings&quot; component={Settings} /&gt;
20
21const CustomRoute = ({ isLoggedIn, ...props }) =&gt; {
22  const location = useLocation();
23  return isLoggedIn? (
24    &lt;Route {...props} /&gt;
25  ) : (
26    &lt;Redirect
27      to={{
28        pathname: `/login/${location.search}`,
29        state: { location },
30      }}
31    /&gt;
32  );
33};
34

...

1const PrivateRoute = ({ isLoggedIn, component: Component, ...rest }) =&gt; {
2  return (
3    &lt;Route
4      {...rest}
5      render={(props) =&gt;
6        isLoggedIn? (
7          &lt;Component {...props} /&gt;
8        ) : (
9          &lt;Redirect
10            to={{ pathname: `/login/${props.location.search}`, state: { from: props.location } }}
11          /&gt;
12        )
13      }
14    /&gt;
15  );
16};
17
18
19&lt;PrivateRoute exact isLoggedIn={isLoggedIn} path=&quot;/settings&quot; component={Settings} /&gt;
20
21const CustomRoute = ({ isLoggedIn, ...props }) =&gt; {
22  const location = useLocation();
23  return isLoggedIn? (
24    &lt;Route {...props} /&gt;
25  ) : (
26    &lt;Redirect
27      to={{
28        pathname: `/login/${location.search}`,
29        state: { location },
30      }}
31    /&gt;
32  );
33};
34&lt;PrivateRoute
35  exact
36  isLoggedIn={isLoggedIn}
37  path=&quot;/settings&quot;
38  component={Settings}
39/&gt;
40

v6 - Custom Wrapper

Takes props and conditionally renders an Outlet component for nested Route components to be rendered into or a Navigate component with route state holding the current location.

1const PrivateRoute = ({ isLoggedIn, component: Component, ...rest }) =&gt; {
2  return (
3    &lt;Route
4      {...rest}
5      render={(props) =&gt;
6        isLoggedIn? (
7          &lt;Component {...props} /&gt;
8        ) : (
9          &lt;Redirect
10            to={{ pathname: `/login/${props.location.search}`, state: { from: props.location } }}
11          /&gt;
12        )
13      }
14    /&gt;
15  );
16};
17
18
19&lt;PrivateRoute exact isLoggedIn={isLoggedIn} path=&quot;/settings&quot; component={Settings} /&gt;
20
21const CustomRoute = ({ isLoggedIn, ...props }) =&gt; {
22  const location = useLocation();
23  return isLoggedIn? (
24    &lt;Route {...props} /&gt;
25  ) : (
26    &lt;Redirect
27      to={{
28        pathname: `/login/${location.search}`,
29        state: { location },
30      }}
31    /&gt;
32  );
33};
34&lt;PrivateRoute
35  exact
36  isLoggedIn={isLoggedIn}
37  path=&quot;/settings&quot;
38  component={Settings}
39/&gt;
40const CustomWrapper = ({ isLoggedIn, ...props }) =&gt; {
41  const location = useLocation();
42  return isLoggedIn? (
43    &lt;Outlet /&gt;
44  ) : (
45    &lt;Navigate
46      to={`/login/${location.search}`}
47      replace
48      state={{ location }}
49    /&gt;
50  )
51};
52

...

1const PrivateRoute = ({ isLoggedIn, component: Component, ...rest }) =&gt; {
2  return (
3    &lt;Route
4      {...rest}
5      render={(props) =&gt;
6        isLoggedIn? (
7          &lt;Component {...props} /&gt;
8        ) : (
9          &lt;Redirect
10            to={{ pathname: `/login/${props.location.search}`, state: { from: props.location } }}
11          /&gt;
12        )
13      }
14    /&gt;
15  );
16};
17
18
19&lt;PrivateRoute exact isLoggedIn={isLoggedIn} path=&quot;/settings&quot; component={Settings} /&gt;
20
21const CustomRoute = ({ isLoggedIn, ...props }) =&gt; {
22  const location = useLocation();
23  return isLoggedIn? (
24    &lt;Route {...props} /&gt;
25  ) : (
26    &lt;Redirect
27      to={{
28        pathname: `/login/${location.search}`,
29        state: { location },
30      }}
31    /&gt;
32  );
33};
34&lt;PrivateRoute
35  exact
36  isLoggedIn={isLoggedIn}
37  path=&quot;/settings&quot;
38  component={Settings}
39/&gt;
40const CustomWrapper = ({ isLoggedIn, ...props }) =&gt; {
41  const location = useLocation();
42  return isLoggedIn? (
43    &lt;Outlet /&gt;
44  ) : (
45    &lt;Navigate
46      to={`/login/${location.search}`}
47      replace
48      state={{ location }}
49    /&gt;
50  )
51};
52&lt;Route path=&quot;settings&quot; element={&lt;CustomWrapper isLoggedIn={isLoggedIn} /&gt;} &gt;
53  &lt;Route path=&quot;settings&quot; element={&lt;Settings /&gt;} /&gt;
54&lt;/Route&gt;
55

Source https://stackoverflow.com/questions/70358626

QUESTION

Patch request not patching - 403 returned - django rest framework

Asked 2021-Dec-11 at 07:34

I'm trying to test an API endpoint with a patch request to ensure it works.

I'm using APILiveServerTestCase but can't seem to get the permissions required to patch the item. I created one user (adminuser) who is a superadmin with access to everything and all permissions.

My test case looks like this:

1class FutureVehicleURLTest(APILiveServerTestCase):
2    def setUp(self):
3        # Setup users and some vehicle data we can query against
4        management.call_command(&quot;create_users_and_vehicle_data&quot;, verbosity=0)
5        self.user = UserFactory()
6        self.admin_user = User.objects.get(username=&quot;adminuser&quot;)
7        self.future_vehicle = f.FutureVehicleFactory(
8            user=self.user,
9            last_updated_by=self.user,
10        )
11        self.vehicle = f.VehicleFactory(
12            user=self.user,
13            created_by=self.user,
14            modified_by=self.user,
15        )
16        self.url = reverse(&quot;FutureVehicles-list&quot;)
17        self.full_url = self.live_server_url + self.url
18        time = str(datetime.now())
19        self.form_data = {
20            &quot;signature&quot;: &quot;TT&quot;,
21            &quot;purchasing&quot;: True,
22            &quot;confirmed_at&quot;: time,
23        }
24

I've tried this test a number of different ways - all giving the same result (403).

I have setup the python debugger in the test, and I have tried actually going to http://localhost:xxxxx/admin/ in the browser and logging in manually with any user but the page just refreshes when I click to login and I never get 'logged in' to see the admin. I'm not sure if that's because it doesn't completely work from within a debugger like that or not.

My test looks like this (using the Requests library):

1class FutureVehicleURLTest(APILiveServerTestCase):
2    def setUp(self):
3        # Setup users and some vehicle data we can query against
4        management.call_command(&quot;create_users_and_vehicle_data&quot;, verbosity=0)
5        self.user = UserFactory()
6        self.admin_user = User.objects.get(username=&quot;adminuser&quot;)
7        self.future_vehicle = f.FutureVehicleFactory(
8            user=self.user,
9            last_updated_by=self.user,
10        )
11        self.vehicle = f.VehicleFactory(
12            user=self.user,
13            created_by=self.user,
14            modified_by=self.user,
15        )
16        self.url = reverse(&quot;FutureVehicles-list&quot;)
17        self.full_url = self.live_server_url + self.url
18        time = str(datetime.now())
19        self.form_data = {
20            &quot;signature&quot;: &quot;TT&quot;,
21            &quot;purchasing&quot;: True,
22            &quot;confirmed_at&quot;: time,
23        }
24    def test_patch_request_updates_object(self):
25        data_dict = {
26            &quot;signature&quot;: &quot;TT&quot;,
27            &quot;purchasing&quot;: &quot;true&quot;,
28            &quot;confirmed_at&quot;: datetime.now().strftime(&quot;%m/%d/%Y, %H:%M:%S&quot;),
29        }
30        url = self.full_url + str(self.future_vehicle.id) + &quot;/&quot;
31        client = requests.Session()
32        client.auth = HTTPBasicAuth(self.admin_user.username, &quot;test&quot;)
33        client.headers.update({&quot;x-test&quot;: &quot;true&quot;})
34        response = client.get(self.live_server_url + &quot;/admin/&quot;)
35        csrftoken = response.cookies[&quot;csrftoken&quot;]
36        # interact with the api
37        response = client.patch(
38            url,
39            data=json.dumps(data_dict),
40            cookies=response.cookies,
41            headers={
42                &quot;X-Requested-With&quot;: &quot;XMLHttpRequest&quot;,
43                &quot;X-CSRFTOKEN&quot;: csrftoken,
44            },
45        )
46        # RESPONSE GIVES 403 PERMISSION DENIED
47        fte_future_vehicle = FutureVehicle.objects.filter(
48            id=self.future_vehicle.id
49        ).first()
50        # THIS ERRORS WITH '' not equal to 'TT'
51        self.assertEqual(fte_future_vehicle.signature, &quot;TT&quot;)
52

I have tried it very similarly to the documentation using APIRequestFactory and forcing authentication:

1class FutureVehicleURLTest(APILiveServerTestCase):
2    def setUp(self):
3        # Setup users and some vehicle data we can query against
4        management.call_command(&quot;create_users_and_vehicle_data&quot;, verbosity=0)
5        self.user = UserFactory()
6        self.admin_user = User.objects.get(username=&quot;adminuser&quot;)
7        self.future_vehicle = f.FutureVehicleFactory(
8            user=self.user,
9            last_updated_by=self.user,
10        )
11        self.vehicle = f.VehicleFactory(
12            user=self.user,
13            created_by=self.user,
14            modified_by=self.user,
15        )
16        self.url = reverse(&quot;FutureVehicles-list&quot;)
17        self.full_url = self.live_server_url + self.url
18        time = str(datetime.now())
19        self.form_data = {
20            &quot;signature&quot;: &quot;TT&quot;,
21            &quot;purchasing&quot;: True,
22            &quot;confirmed_at&quot;: time,
23        }
24    def test_patch_request_updates_object(self):
25        data_dict = {
26            &quot;signature&quot;: &quot;TT&quot;,
27            &quot;purchasing&quot;: &quot;true&quot;,
28            &quot;confirmed_at&quot;: datetime.now().strftime(&quot;%m/%d/%Y, %H:%M:%S&quot;),
29        }
30        url = self.full_url + str(self.future_vehicle.id) + &quot;/&quot;
31        client = requests.Session()
32        client.auth = HTTPBasicAuth(self.admin_user.username, &quot;test&quot;)
33        client.headers.update({&quot;x-test&quot;: &quot;true&quot;})
34        response = client.get(self.live_server_url + &quot;/admin/&quot;)
35        csrftoken = response.cookies[&quot;csrftoken&quot;]
36        # interact with the api
37        response = client.patch(
38            url,
39            data=json.dumps(data_dict),
40            cookies=response.cookies,
41            headers={
42                &quot;X-Requested-With&quot;: &quot;XMLHttpRequest&quot;,
43                &quot;X-CSRFTOKEN&quot;: csrftoken,
44            },
45        )
46        # RESPONSE GIVES 403 PERMISSION DENIED
47        fte_future_vehicle = FutureVehicle.objects.filter(
48            id=self.future_vehicle.id
49        ).first()
50        # THIS ERRORS WITH '' not equal to 'TT'
51        self.assertEqual(fte_future_vehicle.signature, &quot;TT&quot;)
52    def test_patch_request_updates_object(self):
53        data_dict = {
54            &quot;signature&quot;: &quot;TT&quot;,
55            &quot;purchasing&quot;: &quot;true&quot;,
56            &quot;confirmed_at&quot;: datetime.now().strftime(&quot;%m/%d/%Y, %H:%M:%S&quot;),
57        }
58        url = self.full_url + str(self.future_vehicle.id) + &quot;/&quot;
59        api_req_factory = APIRequestFactory()
60        view = FutureVehicleViewSet.as_view({&quot;patch&quot;: &quot;partial_update&quot;})
61        api_request = api_req_factory.patch(
62            url, json.dumps(data_dict), content_type=&quot;application/json&quot;
63        )
64        force_authenticate(api_request, self.admin_user)
65        response = view(api_request, pk=self.future_assignment.id)
66        fte_future_assignment = FutureVehicle.objects.filter(
67            id=self.future_assignment.id
68        ).first()
69        self.assertEqual(fte_future_assignment.signature, &quot;TT&quot;)
70

If I enter the debugger to look at the responses, it's always a 403.

The viewset itself is very simple:

1class FutureVehicleURLTest(APILiveServerTestCase):
2    def setUp(self):
3        # Setup users and some vehicle data we can query against
4        management.call_command(&quot;create_users_and_vehicle_data&quot;, verbosity=0)
5        self.user = UserFactory()
6        self.admin_user = User.objects.get(username=&quot;adminuser&quot;)
7        self.future_vehicle = f.FutureVehicleFactory(
8            user=self.user,
9            last_updated_by=self.user,
10        )
11        self.vehicle = f.VehicleFactory(
12            user=self.user,
13            created_by=self.user,
14            modified_by=self.user,
15        )
16        self.url = reverse(&quot;FutureVehicles-list&quot;)
17        self.full_url = self.live_server_url + self.url
18        time = str(datetime.now())
19        self.form_data = {
20            &quot;signature&quot;: &quot;TT&quot;,
21            &quot;purchasing&quot;: True,
22            &quot;confirmed_at&quot;: time,
23        }
24    def test_patch_request_updates_object(self):
25        data_dict = {
26            &quot;signature&quot;: &quot;TT&quot;,
27            &quot;purchasing&quot;: &quot;true&quot;,
28            &quot;confirmed_at&quot;: datetime.now().strftime(&quot;%m/%d/%Y, %H:%M:%S&quot;),
29        }
30        url = self.full_url + str(self.future_vehicle.id) + &quot;/&quot;
31        client = requests.Session()
32        client.auth = HTTPBasicAuth(self.admin_user.username, &quot;test&quot;)
33        client.headers.update({&quot;x-test&quot;: &quot;true&quot;})
34        response = client.get(self.live_server_url + &quot;/admin/&quot;)
35        csrftoken = response.cookies[&quot;csrftoken&quot;]
36        # interact with the api
37        response = client.patch(
38            url,
39            data=json.dumps(data_dict),
40            cookies=response.cookies,
41            headers={
42                &quot;X-Requested-With&quot;: &quot;XMLHttpRequest&quot;,
43                &quot;X-CSRFTOKEN&quot;: csrftoken,
44            },
45        )
46        # RESPONSE GIVES 403 PERMISSION DENIED
47        fte_future_vehicle = FutureVehicle.objects.filter(
48            id=self.future_vehicle.id
49        ).first()
50        # THIS ERRORS WITH '' not equal to 'TT'
51        self.assertEqual(fte_future_vehicle.signature, &quot;TT&quot;)
52    def test_patch_request_updates_object(self):
53        data_dict = {
54            &quot;signature&quot;: &quot;TT&quot;,
55            &quot;purchasing&quot;: &quot;true&quot;,
56            &quot;confirmed_at&quot;: datetime.now().strftime(&quot;%m/%d/%Y, %H:%M:%S&quot;),
57        }
58        url = self.full_url + str(self.future_vehicle.id) + &quot;/&quot;
59        api_req_factory = APIRequestFactory()
60        view = FutureVehicleViewSet.as_view({&quot;patch&quot;: &quot;partial_update&quot;})
61        api_request = api_req_factory.patch(
62            url, json.dumps(data_dict), content_type=&quot;application/json&quot;
63        )
64        force_authenticate(api_request, self.admin_user)
65        response = view(api_request, pk=self.future_assignment.id)
66        fte_future_assignment = FutureVehicle.objects.filter(
67            id=self.future_assignment.id
68        ).first()
69        self.assertEqual(fte_future_assignment.signature, &quot;TT&quot;)
70class FutureVehicleViewSet(ModelViewSet):
71    serializer_class = FutureVehicleSerializer
72
73    def get_queryset(self):
74        queryset = FutureVehicle.exclude_denied.all()
75        user_id = self.request.query_params.get(&quot;user_id&quot;, None)
76        if user_id:
77            queryset = queryset.filter(user_id=user_id)
78        return queryset
79

The serializer is just as basic as it gets - it's just the FutureVehicle model and all fields.

I just can't figure out why my user won't login - or if maybe I'm doing something wrong in my attempts to patch?

I'm pretty new to Django Rest Framework in general, so any guidances is helpful!

Edit to add - my DRF Settings look like this:

1class FutureVehicleURLTest(APILiveServerTestCase):
2    def setUp(self):
3        # Setup users and some vehicle data we can query against
4        management.call_command(&quot;create_users_and_vehicle_data&quot;, verbosity=0)
5        self.user = UserFactory()
6        self.admin_user = User.objects.get(username=&quot;adminuser&quot;)
7        self.future_vehicle = f.FutureVehicleFactory(
8            user=self.user,
9            last_updated_by=self.user,
10        )
11        self.vehicle = f.VehicleFactory(
12            user=self.user,
13            created_by=self.user,
14            modified_by=self.user,
15        )
16        self.url = reverse(&quot;FutureVehicles-list&quot;)
17        self.full_url = self.live_server_url + self.url
18        time = str(datetime.now())
19        self.form_data = {
20            &quot;signature&quot;: &quot;TT&quot;,
21            &quot;purchasing&quot;: True,
22            &quot;confirmed_at&quot;: time,
23        }
24    def test_patch_request_updates_object(self):
25        data_dict = {
26            &quot;signature&quot;: &quot;TT&quot;,
27            &quot;purchasing&quot;: &quot;true&quot;,
28            &quot;confirmed_at&quot;: datetime.now().strftime(&quot;%m/%d/%Y, %H:%M:%S&quot;),
29        }
30        url = self.full_url + str(self.future_vehicle.id) + &quot;/&quot;
31        client = requests.Session()
32        client.auth = HTTPBasicAuth(self.admin_user.username, &quot;test&quot;)
33        client.headers.update({&quot;x-test&quot;: &quot;true&quot;})
34        response = client.get(self.live_server_url + &quot;/admin/&quot;)
35        csrftoken = response.cookies[&quot;csrftoken&quot;]
36        # interact with the api
37        response = client.patch(
38            url,
39            data=json.dumps(data_dict),
40            cookies=response.cookies,
41            headers={
42                &quot;X-Requested-With&quot;: &quot;XMLHttpRequest&quot;,
43                &quot;X-CSRFTOKEN&quot;: csrftoken,
44            },
45        )
46        # RESPONSE GIVES 403 PERMISSION DENIED
47        fte_future_vehicle = FutureVehicle.objects.filter(
48            id=self.future_vehicle.id
49        ).first()
50        # THIS ERRORS WITH '' not equal to 'TT'
51        self.assertEqual(fte_future_vehicle.signature, &quot;TT&quot;)
52    def test_patch_request_updates_object(self):
53        data_dict = {
54            &quot;signature&quot;: &quot;TT&quot;,
55            &quot;purchasing&quot;: &quot;true&quot;,
56            &quot;confirmed_at&quot;: datetime.now().strftime(&quot;%m/%d/%Y, %H:%M:%S&quot;),
57        }
58        url = self.full_url + str(self.future_vehicle.id) + &quot;/&quot;
59        api_req_factory = APIRequestFactory()
60        view = FutureVehicleViewSet.as_view({&quot;patch&quot;: &quot;partial_update&quot;})
61        api_request = api_req_factory.patch(
62            url, json.dumps(data_dict), content_type=&quot;application/json&quot;
63        )
64        force_authenticate(api_request, self.admin_user)
65        response = view(api_request, pk=self.future_assignment.id)
66        fte_future_assignment = FutureVehicle.objects.filter(
67            id=self.future_assignment.id
68        ).first()
69        self.assertEqual(fte_future_assignment.signature, &quot;TT&quot;)
70class FutureVehicleViewSet(ModelViewSet):
71    serializer_class = FutureVehicleSerializer
72
73    def get_queryset(self):
74        queryset = FutureVehicle.exclude_denied.all()
75        user_id = self.request.query_params.get(&quot;user_id&quot;, None)
76        if user_id:
77            queryset = queryset.filter(user_id=user_id)
78        return queryset
79REST_FRAMEWORK = {
80    &quot;DEFAULT_PAGINATION_CLASS&quot;: &quot;rest_framework.pagination.LimitOffsetPagination&quot;,
81    &quot;DATETIME_FORMAT&quot;: &quot;%m/%d/%Y - %I:%M:%S %p&quot;,
82    &quot;DATE_INPUT_FORMATS&quot;: [&quot;%Y-%m-%d&quot;],
83    &quot;DEFAULT_AUTHENTICATION_CLASSES&quot;: [
84        # Enabling this it will require Django Session (Including CSRF)
85        &quot;rest_framework.authentication.SessionAuthentication&quot;
86    ],
87    &quot;DEFAULT_PERMISSION_CLASSES&quot;: [
88        # Globally only allow IsAuthenticated users access to API Endpoints
89        &quot;rest_framework.permissions.IsAuthenticated&quot;
90    ],
91}
92

I'm certain adminuser is the user we wish to login - if I go into the debugger and check the users, they exist as a user. During creation, any user created has a password set to 'test'.

ANSWER

Answered 2021-Dec-11 at 07:34
Recommended Solution

The test you have written is also testing the Django framework logic (ie: Django admin login). I recommend testing your own functionality, which occurs after login to the Django admin. Django's testing framework offers a helper for logging into the admin, client.login. This allows you to focus on testing your own business logic/not need to maintain internal django authentication business logic tests, which may change release to release.

1class FutureVehicleURLTest(APILiveServerTestCase):
2    def setUp(self):
3        # Setup users and some vehicle data we can query against
4        management.call_command(&quot;create_users_and_vehicle_data&quot;, verbosity=0)
5        self.user = UserFactory()
6        self.admin_user = User.objects.get(username=&quot;adminuser&quot;)
7        self.future_vehicle = f.FutureVehicleFactory(
8            user=self.user,
9            last_updated_by=self.user,
10        )
11        self.vehicle = f.VehicleFactory(
12            user=self.user,
13            created_by=self.user,
14            modified_by=self.user,
15        )
16        self.url = reverse(&quot;FutureVehicles-list&quot;)
17        self.full_url = self.live_server_url + self.url
18        time = str(datetime.now())
19        self.form_data = {
20            &quot;signature&quot;: &quot;TT&quot;,
21            &quot;purchasing&quot;: True,
22            &quot;confirmed_at&quot;: time,
23        }
24    def test_patch_request_updates_object(self):
25        data_dict = {
26            &quot;signature&quot;: &quot;TT&quot;,
27            &quot;purchasing&quot;: &quot;true&quot;,
28            &quot;confirmed_at&quot;: datetime.now().strftime(&quot;%m/%d/%Y, %H:%M:%S&quot;),
29        }
30        url = self.full_url + str(self.future_vehicle.id) + &quot;/&quot;
31        client = requests.Session()
32        client.auth = HTTPBasicAuth(self.admin_user.username, &quot;test&quot;)
33        client.headers.update({&quot;x-test&quot;: &quot;true&quot;})
34        response = client.get(self.live_server_url + &quot;/admin/&quot;)
35        csrftoken = response.cookies[&quot;csrftoken&quot;]
36        # interact with the api
37        response = client.patch(
38            url,
39            data=json.dumps(data_dict),
40            cookies=response.cookies,
41            headers={
42                &quot;X-Requested-With&quot;: &quot;XMLHttpRequest&quot;,
43                &quot;X-CSRFTOKEN&quot;: csrftoken,
44            },
45        )
46        # RESPONSE GIVES 403 PERMISSION DENIED
47        fte_future_vehicle = FutureVehicle.objects.filter(
48            id=self.future_vehicle.id
49        ).first()
50        # THIS ERRORS WITH '' not equal to 'TT'
51        self.assertEqual(fte_future_vehicle.signature, &quot;TT&quot;)
52    def test_patch_request_updates_object(self):
53        data_dict = {
54            &quot;signature&quot;: &quot;TT&quot;,
55            &quot;purchasing&quot;: &quot;true&quot;,
56            &quot;confirmed_at&quot;: datetime.now().strftime(&quot;%m/%d/%Y, %H:%M:%S&quot;),
57        }
58        url = self.full_url + str(self.future_vehicle.id) + &quot;/&quot;
59        api_req_factory = APIRequestFactory()
60        view = FutureVehicleViewSet.as_view({&quot;patch&quot;: &quot;partial_update&quot;})
61        api_request = api_req_factory.patch(
62            url, json.dumps(data_dict), content_type=&quot;application/json&quot;
63        )
64        force_authenticate(api_request, self.admin_user)
65        response = view(api_request, pk=self.future_assignment.id)
66        fte_future_assignment = FutureVehicle.objects.filter(
67            id=self.future_assignment.id
68        ).first()
69        self.assertEqual(fte_future_assignment.signature, &quot;TT&quot;)
70class FutureVehicleViewSet(ModelViewSet):
71    serializer_class = FutureVehicleSerializer
72
73    def get_queryset(self):
74        queryset = FutureVehicle.exclude_denied.all()
75        user_id = self.request.query_params.get(&quot;user_id&quot;, None)
76        if user_id:
77            queryset = queryset.filter(user_id=user_id)
78        return queryset
79REST_FRAMEWORK = {
80    &quot;DEFAULT_PAGINATION_CLASS&quot;: &quot;rest_framework.pagination.LimitOffsetPagination&quot;,
81    &quot;DATETIME_FORMAT&quot;: &quot;%m/%d/%Y - %I:%M:%S %p&quot;,
82    &quot;DATE_INPUT_FORMATS&quot;: [&quot;%Y-%m-%d&quot;],
83    &quot;DEFAULT_AUTHENTICATION_CLASSES&quot;: [
84        # Enabling this it will require Django Session (Including CSRF)
85        &quot;rest_framework.authentication.SessionAuthentication&quot;
86    ],
87    &quot;DEFAULT_PERMISSION_CLASSES&quot;: [
88        # Globally only allow IsAuthenticated users access to API Endpoints
89        &quot;rest_framework.permissions.IsAuthenticated&quot;
90    ],
91}
92from django.test import TestCase, Client
93
94
95def TestCase():
96   client.login(username=self.username, password=self.password)
97
Alternative Solution

However, if you must replicate and manage the business logic of what client.login is doing, here's some of the business logic from Django:

1class FutureVehicleURLTest(APILiveServerTestCase):
2    def setUp(self):
3        # Setup users and some vehicle data we can query against
4        management.call_command(&quot;create_users_and_vehicle_data&quot;, verbosity=0)
5        self.user = UserFactory()
6        self.admin_user = User.objects.get(username=&quot;adminuser&quot;)
7        self.future_vehicle = f.FutureVehicleFactory(
8            user=self.user,
9            last_updated_by=self.user,
10        )
11        self.vehicle = f.VehicleFactory(
12            user=self.user,
13            created_by=self.user,
14            modified_by=self.user,
15        )
16        self.url = reverse(&quot;FutureVehicles-list&quot;)
17        self.full_url = self.live_server_url + self.url
18        time = str(datetime.now())
19        self.form_data = {
20            &quot;signature&quot;: &quot;TT&quot;,
21            &quot;purchasing&quot;: True,
22            &quot;confirmed_at&quot;: time,
23        }
24    def test_patch_request_updates_object(self):
25        data_dict = {
26            &quot;signature&quot;: &quot;TT&quot;,
27            &quot;purchasing&quot;: &quot;true&quot;,
28            &quot;confirmed_at&quot;: datetime.now().strftime(&quot;%m/%d/%Y, %H:%M:%S&quot;),
29        }
30        url = self.full_url + str(self.future_vehicle.id) + &quot;/&quot;
31        client = requests.Session()
32        client.auth = HTTPBasicAuth(self.admin_user.username, &quot;test&quot;)
33        client.headers.update({&quot;x-test&quot;: &quot;true&quot;})
34        response = client.get(self.live_server_url + &quot;/admin/&quot;)
35        csrftoken = response.cookies[&quot;csrftoken&quot;]
36        # interact with the api
37        response = client.patch(
38            url,
39            data=json.dumps(data_dict),
40            cookies=response.cookies,
41            headers={
42                &quot;X-Requested-With&quot;: &quot;XMLHttpRequest&quot;,
43                &quot;X-CSRFTOKEN&quot;: csrftoken,
44            },
45        )
46        # RESPONSE GIVES 403 PERMISSION DENIED
47        fte_future_vehicle = FutureVehicle.objects.filter(
48            id=self.future_vehicle.id
49        ).first()
50        # THIS ERRORS WITH '' not equal to 'TT'
51        self.assertEqual(fte_future_vehicle.signature, &quot;TT&quot;)
52    def test_patch_request_updates_object(self):
53        data_dict = {
54            &quot;signature&quot;: &quot;TT&quot;,
55            &quot;purchasing&quot;: &quot;true&quot;,
56            &quot;confirmed_at&quot;: datetime.now().strftime(&quot;%m/%d/%Y, %H:%M:%S&quot;),
57        }
58        url = self.full_url + str(self.future_vehicle.id) + &quot;/&quot;
59        api_req_factory = APIRequestFactory()
60        view = FutureVehicleViewSet.as_view({&quot;patch&quot;: &quot;partial_update&quot;})
61        api_request = api_req_factory.patch(
62            url, json.dumps(data_dict), content_type=&quot;application/json&quot;
63        )
64        force_authenticate(api_request, self.admin_user)
65        response = view(api_request, pk=self.future_assignment.id)
66        fte_future_assignment = FutureVehicle.objects.filter(
67            id=self.future_assignment.id
68        ).first()
69        self.assertEqual(fte_future_assignment.signature, &quot;TT&quot;)
70class FutureVehicleViewSet(ModelViewSet):
71    serializer_class = FutureVehicleSerializer
72
73    def get_queryset(self):
74        queryset = FutureVehicle.exclude_denied.all()
75        user_id = self.request.query_params.get(&quot;user_id&quot;, None)
76        if user_id:
77            queryset = queryset.filter(user_id=user_id)
78        return queryset
79REST_FRAMEWORK = {
80    &quot;DEFAULT_PAGINATION_CLASS&quot;: &quot;rest_framework.pagination.LimitOffsetPagination&quot;,
81    &quot;DATETIME_FORMAT&quot;: &quot;%m/%d/%Y - %I:%M:%S %p&quot;,
82    &quot;DATE_INPUT_FORMATS&quot;: [&quot;%Y-%m-%d&quot;],
83    &quot;DEFAULT_AUTHENTICATION_CLASSES&quot;: [
84        # Enabling this it will require Django Session (Including CSRF)
85        &quot;rest_framework.authentication.SessionAuthentication&quot;
86    ],
87    &quot;DEFAULT_PERMISSION_CLASSES&quot;: [
88        # Globally only allow IsAuthenticated users access to API Endpoints
89        &quot;rest_framework.permissions.IsAuthenticated&quot;
90    ],
91}
92from django.test import TestCase, Client
93
94
95def TestCase():
96   client.login(username=self.username, password=self.password)
97    def login(self, **credentials):
98        &quot;&quot;&quot;
99        Set the Factory to appear as if it has successfully logged into a site.
100        Return True if login is possible or False if the provided credentials
101        are incorrect.
102        &quot;&quot;&quot;
103        from django.contrib.auth import authenticate
104        user = authenticate(**credentials)
105        if user:
106            self._login(user)
107            return True
108        return False
109
110    def force_login(self, user, backend=None):
111        def get_backend():
112            from django.contrib.auth import load_backend
113            for backend_path in settings.AUTHENTICATION_BACKENDS:
114                backend = load_backend(backend_path)
115                if hasattr(backend, 'get_user'):
116                    return backend_path
117
118        if backend is None:
119            backend = get_backend()
120        user.backend = backend
121        self._login(user, backend)
122
123    def _login(self, user, backend=None):
124        from django.contrib.auth import login
125
126        # Create a fake request to store login details.
127        request = HttpRequest()
128        if self.session:
129            request.session = self.session
130        else:
131            engine = import_module(settings.SESSION_ENGINE)
132            request.session = engine.SessionStore()
133        login(request, user, backend)
134        # Save the session values.
135        request.session.save()
136        # Set the cookie to represent the session.
137        session_cookie = settings.SESSION_COOKIE_NAME
138        self.cookies[session_cookie] = request.session.session_key
139        cookie_data = {
140            'max-age': None,
141            'path': '/',
142            'domain': settings.SESSION_COOKIE_DOMAIN,
143            'secure': settings.SESSION_COOKIE_SECURE or None,
144            'expires': None,
145        }
146        self.cookies[session_cookie].update(cookie_data)
147

Source https://stackoverflow.com/questions/70221003

QUESTION

Haskell: Can I read integers directly into an array?

Asked 2021-Dec-05 at 11:40

In this programming problem, the input is an n×m integer matrix. Typically, n≈ 105 and m ≈ 10. The official solution (1606D, Tutorial) is quite imperative: it involves some matrix manipulation, precomputation and aggregation. For fun, I took it as an STUArray implementation exercise.

Issue

I have managed to implement it using STUArray, but still the program takes way more memory than permitted (256MB). Even when run locally, the maximum resident set size is >400 MB. On profiling, reading from stdin seems to be dominating the memory footprint:

profiling

Functions readv and readv.readInt, responsible for parsing integers and saving them into a 2D list, are taking around 50-70 MB, as opposed to around 16 MB = (106 integers) × (8 bytes per integer + 8 bytes per link).

Is there a hope I can get the total memory below 256 MB? I'm already using Text package for input. Maybe I should avoid lists altogether and directly read integers from stdin to the array. How can we do that? Or, is the issue elsewhere?

Code
1{-# OPTIONS_GHC -O2 #-}
2module CF1606D where
3import qualified Data.Text as T
4import qualified Data.Text.IO as TI
5import qualified Data.Text.Read as TR
6import Control.Monad
7import qualified Data.List as DL
8import qualified Data.IntSet as DS
9import Control.Monad.ST
10import Data.Array.ST.Safe
11import Data.Int (Int32)
12import Data.Array.Unboxed
13
14solve :: IO ()
15solve =  do
16  ~[n,m] &lt;- readv      
17  -- 2D list
18  input &lt;- {-# SCC input #-} replicateM (fromIntegral n) readv     
19  let
20      ints = [1..]
21      sorted = DL.sortOn (head.fst) (zip input ints)
22      (rows,indices) = {-# SCC rows_inds #-} unzip sorted    
23      -- 2D list converted into matrix:
24      matrix = mat (fromIntegral n) (fromIntegral m) rows           
25      infinite = 10^7
26      asc x y = [x,x+1..y]
27      desc x y = [y,y-1..x]    
28      -- Four prefix-matrices:
29      tlMax = runSTUArray $ prefixMat max 0 asc asc (subtract 1) (subtract 1) =&lt;&lt; matrix
30      blMin = runSTUArray $ prefixMat min infinite desc asc (+1) (subtract 1) =&lt;&lt; matrix
31      trMin = runSTUArray $ prefixMat min infinite asc desc (subtract 1) (+1) =&lt;&lt; matrix
32      brMax = runSTUArray $ prefixMat max 0 desc desc (+1) (+1) =&lt;&lt; matrix    
33      good _ (i,j)
34        | tlMax!(i,j) &lt; blMin!(i+1,j) &amp;&amp; brMax!(i+1,j+1) &lt; trMin!(i,j+1) = Left (i,j)
35        | otherwise = Right ()
36      {-# INLINABLE good #-}
37      nearAns = foldM good () [(i,j)|i&lt;-[1..n-1],j&lt;-[1..m-1]]
38      ans = either (\(i,j)-&gt; &quot;YES\n&quot; ++ color n (take i indices) ++ &quot; &quot; ++ show j) (const &quot;NO&quot;) nearAns
39  putStrLn ans
40
41type I = Int32
42type S s = (STUArray s (Int, Int) I)
43type R = Int -&gt; Int -&gt; [Int]
44type F = Int -&gt; Int
45
46mat :: Int -&gt; Int -&gt; [[I]] -&gt; ST s (S s)
47mat n m rows = newListArray ((1,1),(n,m)) $ concat rows
48
49prefixMat :: (I-&gt;I-&gt;I) -&gt; I -&gt; R -&gt; R -&gt; F -&gt; F -&gt; S s -&gt; ST s (S s)
50prefixMat opt worst ordi ordj previ prevj mat = do
51  ((ilo,jlo),(ihi,jhi)) &lt;- getBounds mat
52  pre &lt;- newArray ((ilo-1,jlo-1),(ihi+1,jhi+1)) worst
53  forM_ (ordi ilo ihi) $ \i-&gt; do
54    forM_ (ordj jlo jhi) $ \j -&gt; do
55      matij &lt;- readArray mat (i,j)
56      prei &lt;- readArray pre (previ i,j)
57      prej &lt;- readArray pre (i, prevj j)
58      writeArray pre (i,j) (opt (opt prei prej) matij)
59  return pre
60
61color :: Int -&gt; [Int] -&gt; String
62color n inds = let
63  temp = DS.fromList inds
64  colors = [if DS.member i temp then 'B' else 'R' | i&lt;-[1..n]]
65  in colors
66
67readv :: Integral t =&gt; IO [t]
68readv = map readInt . T.words &lt;$&gt; TI.getLine where
69  readInt = fromIntegral . either (const 0) fst . TR.signed TR.decimal
70{-# INLINABLE readv #-}
71
72main :: IO ()
73main = do
74  ~[n] &lt;- readv
75  replicateM_ n solve
76

Quick description of the code above:

  1. Read n rows each having m integers.
  2. Sort the rows by their first element.
  3. Now compute four 'prefix matrices', one from each corner. For top-left and bottom-right corners, it's the prefix-maximum, and for the other two corners, it's the prefix-minimum that we need to compute.
  4. Find a cell [i,j] at which these prefix matrices satisfy the following condition: top_left [i,j] < bottom_left [i,j] and top_right [i,j] > bottom_right [i,j]
  5. For rows 1 through i, mark their original indices (i.e. position in the unsorted input matrix) as Blue. Mark the rest as Red.

Sample input and Commands

Sample input: inp3.txt.

Command:

1{-# OPTIONS_GHC -O2 #-}
2module CF1606D where
3import qualified Data.Text as T
4import qualified Data.Text.IO as TI
5import qualified Data.Text.Read as TR
6import Control.Monad
7import qualified Data.List as DL
8import qualified Data.IntSet as DS
9import Control.Monad.ST
10import Data.Array.ST.Safe
11import Data.Int (Int32)
12import Data.Array.Unboxed
13
14solve :: IO ()
15solve =  do
16  ~[n,m] &lt;- readv      
17  -- 2D list
18  input &lt;- {-# SCC input #-} replicateM (fromIntegral n) readv     
19  let
20      ints = [1..]
21      sorted = DL.sortOn (head.fst) (zip input ints)
22      (rows,indices) = {-# SCC rows_inds #-} unzip sorted    
23      -- 2D list converted into matrix:
24      matrix = mat (fromIntegral n) (fromIntegral m) rows           
25      infinite = 10^7
26      asc x y = [x,x+1..y]
27      desc x y = [y,y-1..x]    
28      -- Four prefix-matrices:
29      tlMax = runSTUArray $ prefixMat max 0 asc asc (subtract 1) (subtract 1) =&lt;&lt; matrix
30      blMin = runSTUArray $ prefixMat min infinite desc asc (+1) (subtract 1) =&lt;&lt; matrix
31      trMin = runSTUArray $ prefixMat min infinite asc desc (subtract 1) (+1) =&lt;&lt; matrix
32      brMax = runSTUArray $ prefixMat max 0 desc desc (+1) (+1) =&lt;&lt; matrix    
33      good _ (i,j)
34        | tlMax!(i,j) &lt; blMin!(i+1,j) &amp;&amp; brMax!(i+1,j+1) &lt; trMin!(i,j+1) = Left (i,j)
35        | otherwise = Right ()
36      {-# INLINABLE good #-}
37      nearAns = foldM good () [(i,j)|i&lt;-[1..n-1],j&lt;-[1..m-1]]
38      ans = either (\(i,j)-&gt; &quot;YES\n&quot; ++ color n (take i indices) ++ &quot; &quot; ++ show j) (const &quot;NO&quot;) nearAns
39  putStrLn ans
40
41type I = Int32
42type S s = (STUArray s (Int, Int) I)
43type R = Int -&gt; Int -&gt; [Int]
44type F = Int -&gt; Int
45
46mat :: Int -&gt; Int -&gt; [[I]] -&gt; ST s (S s)
47mat n m rows = newListArray ((1,1),(n,m)) $ concat rows
48
49prefixMat :: (I-&gt;I-&gt;I) -&gt; I -&gt; R -&gt; R -&gt; F -&gt; F -&gt; S s -&gt; ST s (S s)
50prefixMat opt worst ordi ordj previ prevj mat = do
51  ((ilo,jlo),(ihi,jhi)) &lt;- getBounds mat
52  pre &lt;- newArray ((ilo-1,jlo-1),(ihi+1,jhi+1)) worst
53  forM_ (ordi ilo ihi) $ \i-&gt; do
54    forM_ (ordj jlo jhi) $ \j -&gt; do
55      matij &lt;- readArray mat (i,j)
56      prei &lt;- readArray pre (previ i,j)
57      prej &lt;- readArray pre (i, prevj j)
58      writeArray pre (i,j) (opt (opt prei prej) matij)
59  return pre
60
61color :: Int -&gt; [Int] -&gt; String
62color n inds = let
63  temp = DS.fromList inds
64  colors = [if DS.member i temp then 'B' else 'R' | i&lt;-[1..n]]
65  in colors
66
67readv :: Integral t =&gt; IO [t]
68readv = map readInt . T.words &lt;$&gt; TI.getLine where
69  readInt = fromIntegral . either (const 0) fst . TR.signed TR.decimal
70{-# INLINABLE readv #-}
71
72main :: IO ()
73main = do
74  ~[n] &lt;- readv
75  replicateM_ n solve
76&gt; stack ghc -- -main-is CF1606D.main -with-rtsopts=&quot;-s -h -p -P&quot; -rtsopts -prof -fprof-auto CF1606D
77&gt; gtime -v ./CF1606D &lt; inp3.txt &gt; outp
78    ...
79    ...
80    MUT     time    2.990s  (  3.744s elapsed)    #    RTS -s output
81    GC      time    4.525s  (  6.231s elapsed)    #    RTS -s output
82    ...
83    ...
84    Maximum resident set size (kbytes): 408532    #    &gt;256 MB (gtime output)
85
86&gt; stack exec -- hp2ps -t0.1 -e8in -c CF1606D.hp &amp;&amp; open CF1606D.ps
87

Question about GC: As shown above in the +RTS -s output, GC seems to be taking longer than the actual logic execution. Is this normal? Is there a way to visualize the GC activity over time? I tried making matrices strict but that didn't have any impact.

Probably this is not a functional-friendly problem at all (although I'll be happy to be disproved on this). For example, Java uses GC too but there are lots of successful Java submissions. Still, I want to see how far I can push. Thanks!

ANSWER

Answered 2021-Dec-05 at 11:40

Contrary to common belief Haskell is quite friendly with respect to problems like that. The real issue is that the array library that comes with GHC is total garbage. Another big problem is that everyone is taught in Haskell to use lists where arrays should be used instead, which is usually one of the major sources of slow code and memory bloated programs. So, it is not surprising that GC takes a long time, it is because there is way too much stuff being allocation. Here is a run on the supplied input for the solution provided below:

1{-# OPTIONS_GHC -O2 #-}
2module CF1606D where
3import qualified Data.Text as T
4import qualified Data.Text.IO as TI
5import qualified Data.Text.Read as TR
6import Control.Monad
7import qualified Data.List as DL
8import qualified Data.IntSet as DS
9import Control.Monad.ST
10import Data.Array.ST.Safe
11import Data.Int (Int32)
12import Data.Array.Unboxed
13
14solve :: IO ()
15solve =  do
16  ~[n,m] &lt;- readv      
17  -- 2D list
18  input &lt;- {-# SCC input #-} replicateM (fromIntegral n) readv     
19  let
20      ints = [1..]
21      sorted = DL.sortOn (head.fst) (zip input ints)
22      (rows,indices) = {-# SCC rows_inds #-} unzip sorted    
23      -- 2D list converted into matrix:
24      matrix = mat (fromIntegral n) (fromIntegral m) rows           
25      infinite = 10^7
26      asc x y = [x,x+1..y]
27      desc x y = [y,y-1..x]    
28      -- Four prefix-matrices:
29      tlMax = runSTUArray $ prefixMat max 0 asc asc (subtract 1) (subtract 1) =&lt;&lt; matrix
30      blMin = runSTUArray $ prefixMat min infinite desc asc (+1) (subtract 1) =&lt;&lt; matrix
31      trMin = runSTUArray $ prefixMat min infinite asc desc (subtract 1) (+1) =&lt;&lt; matrix
32      brMax = runSTUArray $ prefixMat max 0 desc desc (+1) (+1) =&lt;&lt; matrix    
33      good _ (i,j)
34        | tlMax!(i,j) &lt; blMin!(i+1,j) &amp;&amp; brMax!(i+1,j+1) &lt; trMin!(i,j+1) = Left (i,j)
35        | otherwise = Right ()
36      {-# INLINABLE good #-}
37      nearAns = foldM good () [(i,j)|i&lt;-[1..n-1],j&lt;-[1..m-1]]
38      ans = either (\(i,j)-&gt; &quot;YES\n&quot; ++ color n (take i indices) ++ &quot; &quot; ++ show j) (const &quot;NO&quot;) nearAns
39  putStrLn ans
40
41type I = Int32
42type S s = (STUArray s (Int, Int) I)
43type R = Int -&gt; Int -&gt; [Int]
44type F = Int -&gt; Int
45
46mat :: Int -&gt; Int -&gt; [[I]] -&gt; ST s (S s)
47mat n m rows = newListArray ((1,1),(n,m)) $ concat rows
48
49prefixMat :: (I-&gt;I-&gt;I) -&gt; I -&gt; R -&gt; R -&gt; F -&gt; F -&gt; S s -&gt; ST s (S s)
50prefixMat opt worst ordi ordj previ prevj mat = do
51  ((ilo,jlo),(ihi,jhi)) &lt;- getBounds mat
52  pre &lt;- newArray ((ilo-1,jlo-1),(ihi+1,jhi+1)) worst
53  forM_ (ordi ilo ihi) $ \i-&gt; do
54    forM_ (ordj jlo jhi) $ \j -&gt; do
55      matij &lt;- readArray mat (i,j)
56      prei &lt;- readArray pre (previ i,j)
57      prej &lt;- readArray pre (i, prevj j)
58      writeArray pre (i,j) (opt (opt prei prej) matij)
59  return pre
60
61color :: Int -&gt; [Int] -&gt; String
62color n inds = let
63  temp = DS.fromList inds
64  colors = [if DS.member i temp then 'B' else 'R' | i&lt;-[1..n]]
65  in colors
66
67readv :: Integral t =&gt; IO [t]
68readv = map readInt . T.words &lt;$&gt; TI.getLine where
69  readInt = fromIntegral . either (const 0) fst . TR.signed TR.decimal
70{-# INLINABLE readv #-}
71
72main :: IO ()
73main = do
74  ~[n] &lt;- readv
75  replicateM_ n solve
76&gt; stack ghc -- -main-is CF1606D.main -with-rtsopts=&quot;-s -h -p -P&quot; -rtsopts -prof -fprof-auto CF1606D
77&gt; gtime -v ./CF1606D &lt; inp3.txt &gt; outp
78    ...
79    ...
80    MUT     time    2.990s  (  3.744s elapsed)    #    RTS -s output
81    GC      time    4.525s  (  6.231s elapsed)    #    RTS -s output
82    ...
83    ...
84    Maximum resident set size (kbytes): 408532    #    &gt;256 MB (gtime output)
85
86&gt; stack exec -- hp2ps -t0.1 -e8in -c CF1606D.hp &amp;&amp; open CF1606D.ps
87   1,483,547,096 bytes allocated in the heap
88         566,448 bytes copied during GC
89      18,703,640 bytes maximum residency (3 sample(s))
90       1,223,400 bytes maximum slop
91              32 MiB total memory in use (0 MB lost due to fragmentation)
92
93                                     Tot time (elapsed)  Avg pause  Max pause
94  Gen  0      1399 colls,     0 par    0.009s   0.009s     0.0000s    0.0011s
95  Gen  1         3 colls,     0 par    0.002s   0.002s     0.0006s    0.0016s
96
97  TASKS: 4 (1 bound, 3 peak workers (3 total), using -N1)
98
99  SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)
100
101  INIT    time    0.001s  (  0.001s elapsed)
102  MUT     time    0.484s  (  0.517s elapsed)
103  GC      time    0.011s  (  0.011s elapsed)
104  EXIT    time    0.001s  (  0.002s elapsed)
105  Total   time    0.496s  (  0.530s elapsed)
106

The solution provided below uses an array library massiv, which makes it impossible to submit to codeforces. However, hopefully the goal is to get better at Haskell, rather than get points on some website.

The red-blue matrix can be separated into two stages: read and solve

Read Read the dimensions

In the main function we only read total number of arrays and dimensions for each array. Also we print the outcome. Nothing exciting here. (Note that the linked file inp3.txt has a larger array than the limits defined in the problem: n*m <= 10^6)

1{-# OPTIONS_GHC -O2 #-}
2module CF1606D where
3import qualified Data.Text as T
4import qualified Data.Text.IO as TI
5import qualified Data.Text.Read as TR
6import Control.Monad
7import qualified Data.List as DL
8import qualified Data.IntSet as DS
9import Control.Monad.ST
10import Data.Array.ST.Safe
11import Data.Int (Int32)
12import Data.Array.Unboxed
13
14solve :: IO ()
15solve =  do
16  ~[n,m] &lt;- readv      
17  -- 2D list
18  input &lt;- {-# SCC input #-} replicateM (fromIntegral n) readv     
19  let
20      ints = [1..]
21      sorted = DL.sortOn (head.fst) (zip input ints)
22      (rows,indices) = {-# SCC rows_inds #-} unzip sorted    
23      -- 2D list converted into matrix:
24      matrix = mat (fromIntegral n) (fromIntegral m) rows           
25      infinite = 10^7
26      asc x y = [x,x+1..y]
27      desc x y = [y,y-1..x]    
28      -- Four prefix-matrices:
29      tlMax = runSTUArray $ prefixMat max 0 asc asc (subtract 1) (subtract 1) =&lt;&lt; matrix
30      blMin = runSTUArray $ prefixMat min infinite desc asc (+1) (subtract 1) =&lt;&lt; matrix
31      trMin = runSTUArray $ prefixMat min infinite asc desc (subtract 1) (+1) =&lt;&lt; matrix
32      brMax = runSTUArray $ prefixMat max 0 desc desc (+1) (+1) =&lt;&lt; matrix    
33      good _ (i,j)
34        | tlMax!(i,j) &lt; blMin!(i+1,j) &amp;&amp; brMax!(i+1,j+1) &lt; trMin!(i,j+1) = Left (i,j)
35        | otherwise = Right ()
36      {-# INLINABLE good #-}
37      nearAns = foldM good () [(i,j)|i&lt;-[1..n-1],j&lt;-[1..m-1]]
38      ans = either (\(i,j)-&gt; &quot;YES\n&quot; ++ color n (take i indices) ++ &quot; &quot; ++ show j) (const &quot;NO&quot;) nearAns
39  putStrLn ans
40
41type I = Int32
42type S s = (STUArray s (Int, Int) I)
43type R = Int -&gt; Int -&gt; [Int]
44type F = Int -&gt; Int
45
46mat :: Int -&gt; Int -&gt; [[I]] -&gt; ST s (S s)
47mat n m rows = newListArray ((1,1),(n,m)) $ concat rows
48
49prefixMat :: (I-&gt;I-&gt;I) -&gt; I -&gt; R -&gt; R -&gt; F -&gt; F -&gt; S s -&gt; ST s (S s)
50prefixMat opt worst ordi ordj previ prevj mat = do
51  ((ilo,jlo),(ihi,jhi)) &lt;- getBounds mat
52  pre &lt;- newArray ((ilo-1,jlo-1),(ihi+1,jhi+1)) worst
53  forM_ (ordi ilo ihi) $ \i-&gt; do
54    forM_ (ordj jlo jhi) $ \j -&gt; do
55      matij &lt;- readArray mat (i,j)
56      prei &lt;- readArray pre (previ i,j)
57      prej &lt;- readArray pre (i, prevj j)
58      writeArray pre (i,j) (opt (opt prei prej) matij)
59  return pre
60
61color :: Int -&gt; [Int] -&gt; String
62color n inds = let
63  temp = DS.fromList inds
64  colors = [if DS.member i temp then 'B' else 'R' | i&lt;-[1..n]]
65  in colors
66
67readv :: Integral t =&gt; IO [t]
68readv = map readInt . T.words &lt;$&gt; TI.getLine where
69  readInt = fromIntegral . either (const 0) fst . TR.signed TR.decimal
70{-# INLINABLE readv #-}
71
72main :: IO ()
73main = do
74  ~[n] &lt;- readv
75  replicateM_ n solve
76&gt; stack ghc -- -main-is CF1606D.main -with-rtsopts=&quot;-s -h -p -P&quot; -rtsopts -prof -fprof-auto CF1606D
77&gt; gtime -v ./CF1606D &lt; inp3.txt &gt; outp
78    ...
79    ...
80    MUT     time    2.990s  (  3.744s elapsed)    #    RTS -s output
81    GC      time    4.525s  (  6.231s elapsed)    #    RTS -s output
82    ...
83    ...
84    Maximum resident set size (kbytes): 408532    #    &gt;256 MB (gtime output)
85
86&gt; stack exec -- hp2ps -t0.1 -e8in -c CF1606D.hp &amp;&amp; open CF1606D.ps
87   1,483,547,096 bytes allocated in the heap
88         566,448 bytes copied during GC
89      18,703,640 bytes maximum residency (3 sample(s))
90       1,223,400 bytes maximum slop
91              32 MiB total memory in use (0 MB lost due to fragmentation)
92
93                                     Tot time (elapsed)  Avg pause  Max pause
94  Gen  0      1399 colls,     0 par    0.009s   0.009s     0.0000s    0.0011s
95  Gen  1         3 colls,     0 par    0.002s   0.002s     0.0006s    0.0016s
96
97  TASKS: 4 (1 bound, 3 peak workers (3 total), using -N1)
98
99  SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)
100
101  INIT    time    0.001s  (  0.001s elapsed)
102  MUT     time    0.484s  (  0.517s elapsed)
103  GC      time    0.011s  (  0.011s elapsed)
104  EXIT    time    0.001s  (  0.002s elapsed)
105  Total   time    0.496s  (  0.530s elapsed)
106import Control.Monad.ST
107import Control.Monad
108import qualified Data.ByteString as BS
109import Data.Massiv.Array as A hiding (B)
110import Data.Massiv.Array.Mutable.Algorithms (quicksortByM_)
111import Control.Scheduler (trivialScheduler_)
112
113main :: IO ()
114main = do
115  t &lt;- Prelude.read &lt;$&gt; getLine
116  when (t &lt; 1 || t &gt; 1000) $ error $ &quot;Invalid t: &quot; ++ show t
117  replicateM_ t $ do
118    dimsStr &lt;- getLine
119    case Prelude.map Prelude.read (words dimsStr) of
120      -- Test file fails this check: &amp;&amp; n * m &lt;= 10 ^ (6 :: Int) -&gt; do
121      [n, m] | n &gt;= 2 &amp;&amp; m &gt; 0 &amp;&amp; m &lt;= 5 * 10 ^ (5 :: Int) -&gt; do
122        mat &lt;- readMatrix n m
123        case solve mat of
124          Nothing -&gt; putStrLn &quot;NO&quot;
125          Just (ix, cs) -&gt; do
126            putStrLn &quot;YES&quot;
127            putStr $ foldMap show cs
128            putStr &quot; &quot;
129            print ix
130      _ -&gt; putStrLn $ &quot;Unexpected dimensions: &quot; ++ show dimsStr
131
Read the array in

Loading the input into array is the major source of problems int the original question:

  • there is no need to rely on text, ascii characters is the only valid input expected by the problem.
  • input is read into a list of lists. That list of lists is the real source of the memory overhead.
  • Sorting lists is ridiculously slow and memory hungry.

Normally in such situation it would be much better to read input in a streaming fashion using something like conduit. In particular, reading input as stream of bytes and parsing those bytes as numbers would be the optimal solution. That being said there are hard requirements on the width of each array in the description of the problem, so we can get away with reading input line-by-line as a ByteString and then parsing numbers (assumed unsigned for simplicity) in each line and write those numbers into array at the same time. This ensures that at this stage we will only have allocated the resulting array and a single line as sequence of bytes. This could be done cleaner with a parsing library like attoparsec, but problem is simple enough to just do it adhoc.

1{-# OPTIONS_GHC -O2 #-}
2module CF1606D where
3import qualified Data.Text as T
4import qualified Data.Text.IO as TI
5import qualified Data.Text.Read as TR
6import Control.Monad
7import qualified Data.List as DL
8import qualified Data.IntSet as DS
9import Control.Monad.ST
10import Data.Array.ST.Safe
11import Data.Int (Int32)
12import Data.Array.Unboxed
13
14solve :: IO ()
15solve =  do
16  ~[n,m] &lt;- readv      
17  -- 2D list
18  input &lt;- {-# SCC input #-} replicateM (fromIntegral n) readv     
19  let
20      ints = [1..]
21      sorted = DL.sortOn (head.fst) (zip input ints)
22      (rows,indices) = {-# SCC rows_inds #-} unzip sorted    
23      -- 2D list converted into matrix:
24      matrix = mat (fromIntegral n) (fromIntegral m) rows           
25      infinite = 10^7
26      asc x y = [x,x+1..y]
27      desc x y = [y,y-1..x]    
28      -- Four prefix-matrices:
29      tlMax = runSTUArray $ prefixMat max 0 asc asc (subtract 1) (subtract 1) =&lt;&lt; matrix
30      blMin = runSTUArray $ prefixMat min infinite desc asc (+1) (subtract 1) =&lt;&lt; matrix
31      trMin = runSTUArray $ prefixMat min infinite asc desc (subtract 1) (+1) =&lt;&lt; matrix
32      brMax = runSTUArray $ prefixMat max 0 desc desc (+1) (+1) =&lt;&lt; matrix    
33      good _ (i,j)
34        | tlMax!(i,j) &lt; blMin!(i+1,j) &amp;&amp; brMax!(i+1,j+1) &lt; trMin!(i,j+1) = Left (i,j)
35        | otherwise = Right ()
36      {-# INLINABLE good #-}
37      nearAns = foldM good () [(i,j)|i&lt;-[1..n-1],j&lt;-[1..m-1]]
38      ans = either (\(i,j)-&gt; &quot;YES\n&quot; ++ color n (take i indices) ++ &quot; &quot; ++ show j) (const &quot;NO&quot;) nearAns
39  putStrLn ans
40
41type I = Int32
42type S s = (STUArray s (Int, Int) I)
43type R = Int -&gt; Int -&gt; [Int]
44type F = Int -&gt; Int
45
46mat :: Int -&gt; Int -&gt; [[I]] -&gt; ST s (S s)
47mat n m rows = newListArray ((1,1),(n,m)) $ concat rows
48
49prefixMat :: (I-&gt;I-&gt;I) -&gt; I -&gt; R -&gt; R -&gt; F -&gt; F -&gt; S s -&gt; ST s (S s)
50prefixMat opt worst ordi ordj previ prevj mat = do
51  ((ilo,jlo),(ihi,jhi)) &lt;- getBounds mat
52  pre &lt;- newArray ((ilo-1,jlo-1),(ihi+1,jhi+1)) worst
53  forM_ (ordi ilo ihi) $ \i-&gt; do
54    forM_ (ordj jlo jhi) $ \j -&gt; do
55      matij &lt;- readArray mat (i,j)
56      prei &lt;- readArray pre (previ i,j)
57      prej &lt;- readArray pre (i, prevj j)
58      writeArray pre (i,j) (opt (opt prei prej) matij)
59  return pre
60
61color :: Int -&gt; [Int] -&gt; String
62color n inds = let
63  temp = DS.fromList inds
64  colors = [if DS.member i temp then 'B' else 'R' | i&lt;-[1..n]]
65  in colors
66
67readv :: Integral t =&gt; IO [t]
68readv = map readInt . T.words &lt;$&gt; TI.getLine where
69  readInt = fromIntegral . either (const 0) fst . TR.signed TR.decimal
70{-# INLINABLE readv #-}
71
72main :: IO ()
73main = do
74  ~[n] &lt;- readv
75  replicateM_ n solve
76&gt; stack ghc -- -main-is CF1606D.main -with-rtsopts=&quot;-s -h -p -P&quot; -rtsopts -prof -fprof-auto CF1606D
77&gt; gtime -v ./CF1606D &lt; inp3.txt &gt; outp
78    ...
79    ...
80    MUT     time    2.990s  (  3.744s elapsed)    #    RTS -s output
81    GC      time    4.525s  (  6.231s elapsed)    #    RTS -s output
82    ...
83    ...
84    Maximum resident set size (kbytes): 408532    #    &gt;256 MB (gtime output)
85
86&gt; stack exec -- hp2ps -t0.1 -e8in -c CF1606D.hp &amp;&amp; open CF1606D.ps
87   1,483,547,096 bytes allocated in the heap
88         566,448 bytes copied during GC
89      18,703,640 bytes maximum residency (3 sample(s))
90       1,223,400 bytes maximum slop
91              32 MiB total memory in use (0 MB lost due to fragmentation)
92
93                                     Tot time (elapsed)  Avg pause  Max pause
94  Gen  0      1399 colls,     0 par    0.009s   0.009s     0.0000s    0.0011s
95  Gen  1         3 colls,     0 par    0.002s   0.002s     0.0006s    0.0016s
96
97  TASKS: 4 (1 bound, 3 peak workers (3 total), using -N1)
98
99  SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)
100
101  INIT    time    0.001s  (  0.001s elapsed)
102  MUT     time    0.484s  (  0.517s elapsed)
103  GC      time    0.011s  (  0.011s elapsed)
104  EXIT    time    0.001s  (  0.002s elapsed)
105  Total   time    0.496s  (  0.530s elapsed)
106import Control.Monad.ST
107import Control.Monad
108import qualified Data.ByteString as BS
109import Data.Massiv.Array as A hiding (B)
110import Data.Massiv.Array.Mutable.Algorithms (quicksortByM_)
111import Control.Scheduler (trivialScheduler_)
112
113main :: IO ()
114main = do
115  t &lt;- Prelude.read &lt;$&gt; getLine
116  when (t &lt; 1 || t &gt; 1000) $ error $ &quot;Invalid t: &quot; ++ show t
117  replicateM_ t $ do
118    dimsStr &lt;- getLine
119    case Prelude.map Prelude.read (words dimsStr) of
120      -- Test file fails this check: &amp;&amp; n * m &lt;= 10 ^ (6 :: Int) -&gt; do
121      [n, m] | n &gt;= 2 &amp;&amp; m &gt; 0 &amp;&amp; m &lt;= 5 * 10 ^ (5 :: Int) -&gt; do
122        mat &lt;- readMatrix n m
123        case solve mat of
124          Nothing -&gt; putStrLn &quot;NO&quot;
125          Just (ix, cs) -&gt; do
126            putStrLn &quot;YES&quot;
127            putStr $ foldMap show cs
128            putStr &quot; &quot;
129            print ix
130      _ -&gt; putStrLn $ &quot;Unexpected dimensions: &quot; ++ show dimsStr
131type Val = Word
132
133readMatrix :: Int -&gt; Int -&gt; IO (Matrix P Val)
134readMatrix n m = createArrayS_ (Sz2 n m) readMMatrix
135
136readMMatrix :: MMatrix RealWorld P Val -&gt; IO ()
137readMMatrix mat =
138  loopM_ 0 (&lt; n) (+ 1) $ \i -&gt; do
139    line &lt;- BS.getLine
140    --- ^ reads at most 10Mb because it is known that input will be at most
141    -- 5*10^5 Words: 19 digits max per Word and one for space: 5*10^5 * 20bytes
142    loopM 0 (&lt; m) (+ 1) line $ \j bs -&gt;
143      let (word, bs') = parseWord bs
144       in bs' &lt;$ write_ mat (i :. j) word
145  where
146    Sz2 n m = sizeOfMArray mat
147    isSpace = (== 32)
148    isDigit w8 = w8 &gt;= 48 &amp;&amp; w8 &lt;= 57
149    parseWord bs =
150      case BS.uncons bs of
151        Just (w8, bs')
152          | isDigit w8 -&gt; parseWordLoop (fromIntegral (w8 - 48)) bs'
153          | otherwise -&gt; error $ &quot;Unexpected byte: &quot; ++ show w8
154        Nothing -&gt; error &quot;Unexpected end of input&quot;
155    parseWordLoop !acc bs =
156      case BS.uncons bs of
157        Nothing -&gt; (acc, bs)
158        Just (w8, bs')
159          | isSpace w8 -&gt; (acc, bs')
160          | isDigit w8 -&gt; parseWordLoop (acc * 10 + fromIntegral (w8 - 48)) bs'
161          | otherwise -&gt; error $ &quot;Unexpected byte: &quot; ++ show w8
162
Solve

This is the step where we implement the actual solution. Instead of going into trying to fix the solution provided in this SO question I went on and translated the C++ solution that was linked in the question instead. Reason I went that route is twofold:

  • C++ soluition is highly imperative and I wanted to demonstrate that imperative array manipulations are not that foreign to Haskell, so I tried to create a translation that was as close as possible.
  • I knew that solution works

Note, that it should be possible to rewrite the solution below with array package, because in the end all that is needed are the read, write and allocate operations.

1{-# OPTIONS_GHC -O2 #-}
2module CF1606D where
3import qualified Data.Text as T
4import qualified Data.Text.IO as TI
5import qualified Data.Text.Read as TR
6import Control.Monad
7import qualified Data.List as DL
8import qualified Data.IntSet as DS
9import Control.Monad.ST
10import Data.Array.ST.Safe
11import Data.Int (Int32)
12import Data.Array.Unboxed
13
14solve :: IO ()
15solve =  do
16  ~[n,m] &lt;- readv      
17  -- 2D list
18  input &lt;- {-# SCC input #-} replicateM (fromIntegral n) readv     
19  let
20      ints = [1..]
21      sorted = DL.sortOn (head.fst) (zip input ints)
22      (rows,indices) = {-# SCC rows_inds #-} unzip sorted    
23      -- 2D list converted into matrix:
24      matrix = mat (fromIntegral n) (fromIntegral m) rows           
25      infinite = 10^7
26      asc x y = [x,x+1..y]
27      desc x y = [y,y-1..x]    
28      -- Four prefix-matrices:
29      tlMax = runSTUArray $ prefixMat max 0 asc asc (subtract 1) (subtract 1) =&lt;&lt; matrix
30      blMin = runSTUArray $ prefixMat min infinite desc asc (+1) (subtract 1) =&lt;&lt; matrix
31      trMin = runSTUArray $ prefixMat min infinite asc desc (subtract 1) (+1) =&lt;&lt; matrix
32      brMax = runSTUArray $ prefixMat max 0 desc desc (+1) (+1) =&lt;&lt; matrix    
33      good _ (i,j)
34        | tlMax!(i,j) &lt; blMin!(i+1,j) &amp;&amp; brMax!(i+1,j+1) &lt; trMin!(i,j+1) = Left (i,j)
35        | otherwise = Right ()
36      {-# INLINABLE good #-}
37      nearAns = foldM good () [(i,j)|i&lt;-[1..n-1],j&lt;-[1..m-1]]
38      ans = either (\(i,j)-&gt; &quot;YES\n&quot; ++ color n (take i indices) ++ &quot; &quot; ++ show j) (const &quot;NO&quot;) nearAns
39  putStrLn ans
40
41type I = Int32
42type S s = (STUArray s (Int, Int) I)
43type R = Int -&gt; Int -&gt; [Int]
44type F = Int -&gt; Int
45
46mat :: Int -&gt; Int -&gt; [[I]] -&gt; ST s (S s)
47mat n m rows = newListArray ((1,1),(n,m)) $ concat rows
48
49prefixMat :: (I-&gt;I-&gt;I) -&gt; I -&gt; R -&gt; R -&gt; F -&gt; F -&gt; S s -&gt; ST s (S s)
50prefixMat opt worst ordi ordj previ prevj mat = do
51  ((ilo,jlo),(ihi,jhi)) &lt;- getBounds mat
52  pre &lt;- newArray ((ilo-1,jlo-1),(ihi+1,jhi+1)) worst
53  forM_ (ordi ilo ihi) $ \i-&gt; do
54    forM_ (ordj jlo jhi) $ \j -&gt; do
55      matij &lt;- readArray mat (i,j)
56      prei &lt;- readArray pre (previ i,j)
57      prej &lt;- readArray pre (i, prevj j)
58      writeArray pre (i,j) (opt (opt prei prej) matij)
59  return pre
60
61color :: Int -&gt; [Int] -&gt; String
62color n inds = let
63  temp = DS.fromList inds
64  colors = [if DS.member i temp then 'B' else 'R' | i&lt;-[1..n]]
65  in colors
66
67readv :: Integral t =&gt; IO [t]
68readv = map readInt . T.words &lt;$&gt; TI.getLine where
69  readInt = fromIntegral . either (const 0) fst . TR.signed TR.decimal
70{-# INLINABLE readv #-}
71
72main :: IO ()
73main = do
74  ~[n] &lt;- readv
75  replicateM_ n solve
76&gt; stack ghc -- -main-is CF1606D.main -with-rtsopts=&quot;-s -h -p -P&quot; -rtsopts -prof -fprof-auto CF1606D
77&gt; gtime -v ./CF1606D &lt; inp3.txt &gt; outp
78    ...
79    ...
80    MUT     time    2.990s  (  3.744s elapsed)    #    RTS -s output
81    GC      time    4.525s  (  6.231s elapsed)    #    RTS -s output
82    ...
83    ...
84    Maximum resident set size (kbytes): 408532    #    &gt;256 MB (gtime output)
85
86&gt; stack exec -- hp2ps -t0.1 -e8in -c CF1606D.hp &amp;&amp; open CF1606D.ps
87   1,483,547,096 bytes allocated in the heap
88         566,448 bytes copied during GC
89      18,703,640 bytes maximum residency (3 sample(s))
90       1,223,400 bytes maximum slop
91              32 MiB total memory in use (0 MB lost due to fragmentation)
92
93                                     Tot time (elapsed)  Avg pause  Max pause
94  Gen  0      1399 colls,     0 par    0.009s   0.009s     0.0000s    0.0011s
95  Gen  1         3 colls,     0 par    0.002s   0.002s     0.0006s    0.0016s
96
97  TASKS: 4 (1 bound, 3 peak workers (3 total), using -N1)
98
99  SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)
100
101  INIT    time    0.001s  (  0.001s elapsed)
102  MUT     time    0.484s  (  0.517s elapsed)
103  GC      time    0.011s  (  0.011s elapsed)
104  EXIT    time    0.001s  (  0.002s elapsed)
105  Total   time    0.496s  (  0.530s elapsed)
106import Control.Monad.ST
107import Control.Monad
108import qualified Data.ByteString as BS
109import Data.Massiv.Array as A hiding (B)
110import Data.Massiv.Array.Mutable.Algorithms (quicksortByM_)
111import Control.Scheduler (trivialScheduler_)
112
113main :: IO ()
114main = do
115  t &lt;- Prelude.read &lt;$&gt; getLine
116  when (t &lt; 1 || t &gt; 1000) $ error $ &quot;Invalid t: &quot; ++ show t
117  replicateM_ t $ do
118    dimsStr &lt;- getLine
119    case Prelude.map Prelude.read (words dimsStr) of
120      -- Test file fails this check: &amp;&amp; n * m &lt;= 10 ^ (6 :: Int) -&gt; do
121      [n, m] | n &gt;= 2 &amp;&amp; m &gt; 0 &amp;&amp; m &lt;= 5 * 10 ^ (5 :: Int) -&gt; do
122        mat &lt;- readMatrix n m
123        case solve mat of
124          Nothing -&gt; putStrLn &quot;NO&quot;
125          Just (ix, cs) -&gt; do
126            putStrLn &quot;YES&quot;
127            putStr $ foldMap show cs
128            putStr &quot; &quot;
129            print ix
130      _ -&gt; putStrLn $ &quot;Unexpected dimensions: &quot; ++ show dimsStr
131type Val = Word
132
133readMatrix :: Int -&gt; Int -&gt; IO (Matrix P Val)
134readMatrix n m = createArrayS_ (Sz2 n m) readMMatrix
135
136readMMatrix :: MMatrix RealWorld P Val -&gt; IO ()
137readMMatrix mat =
138  loopM_ 0 (&lt; n) (+ 1) $ \i -&gt; do
139    line &lt;- BS.getLine
140    --- ^ reads at most 10Mb because it is known that input will be at most
141    -- 5*10^5 Words: 19 digits max per Word and one for space: 5*10^5 * 20bytes
142    loopM 0 (&lt; m) (+ 1) line $ \j bs -&gt;
143      let (word, bs') = parseWord bs
144       in bs' &lt;$ write_ mat (i :. j) word
145  where
146    Sz2 n m = sizeOfMArray mat
147    isSpace = (== 32)
148    isDigit w8 = w8 &gt;= 48 &amp;&amp; w8 &lt;= 57
149    parseWord bs =
150      case BS.uncons bs of
151        Just (w8, bs')
152          | isDigit w8 -&gt; parseWordLoop (fromIntegral (w8 - 48)) bs'
153          | otherwise -&gt; error $ &quot;Unexpected byte: &quot; ++ show w8
154        Nothing -&gt; error &quot;Unexpected end of input&quot;
155    parseWordLoop !acc bs =
156      case BS.uncons bs of
157        Nothing -&gt; (acc, bs)
158        Just (w8, bs')
159          | isSpace w8 -&gt; (acc, bs')
160          | isDigit w8 -&gt; parseWordLoop (acc * 10 + fromIntegral (w8 - 48)) bs'
161          | otherwise -&gt; error $ &quot;Unexpected byte: &quot; ++ show w8
162computeSortBy ::
163     (Load r Ix1 e, Manifest r' e)
164  =&gt; (e -&gt; e -&gt; Ordering)
165  -&gt; Vector r e
166  -&gt; Vector r' e
167computeSortBy f vec = 
168  withLoadMArrayST_ vec $ quicksortByM_ (\x y -&gt; pure $ f x y) trivialScheduler_
169
170solve :: Matrix P Val -&gt; Maybe (Int, [Color])
171solve a = runST $ do
172  let sz@(Sz2 n m) = size a
173      ord :: Vector P Int
174      ord = computeSortBy 
175              (\x y -&gt; compare (a ! (y :. 0)) (a ! (x :. 0))) (0 ..: n)
176  mxl &lt;- newMArray @P sz minBound
177  loopM_ (n - 1) (&gt;= 0) (subtract 1) $ \ i -&gt;
178    loopM_ 0 (&lt; m) (+ 1) $ \j -&gt; do
179      writeM mxl (i :. j) (a ! ((ord ! i) :. j))
180      when (i &lt; n - 1) $
181        writeM mxl (i :. j) 
182          =&lt;&lt; max &lt;$&gt; readM mxl (i :. j) &lt;*&gt; readM mxl (i + 1 :. j)
183      when (j &gt; 0) $
184        writeM mxl (i :. j) 
185          =&lt;&lt; max &lt;$&gt; readM mxl (i :. j) &lt;*&gt; readM mxl (i :. j - 1)
186  mnr &lt;- newMArray @P sz maxBound
187  loopM_ (n - 1) (&gt;= 0) (subtract 1) $ \ i -&gt;
188    loopM_ (m - 1) (&gt;= 0) (subtract 1) $ \ j -&gt; do
189      writeM mnr (i :. j) (a ! ((ord ! i) :. j))
190      when (i &lt; n - 1) $
191        writeM mnr (i :. j) 
192          =&lt;&lt; min &lt;$&gt; readM mnr (i :. j) &lt;*&gt; readM mnr (i + 1 :. j)
193      when (j &lt; m - 1) $
194        writeM mnr (i :. j) 
195          =&lt;&lt; min &lt;$&gt; readM mnr (i :. j) &lt;*&gt; readM mnr (i :. j + 1)
196  mnl &lt;- newMArray @P (Sz m) maxBound
197  mxr &lt;- newMArray @P (Sz m) minBound
198  let goI i
199        | i &lt; n - 1 = do
200          loopM_ 0 (&lt; m) (+ 1) $ \j -&gt; do
201            val &lt;- min (a ! ((ord ! i) :. j)) &lt;$&gt; readM mnl j
202            writeM mnl j val
203            when (j &gt; 0) $
204              writeM mnl j . min val =&lt;&lt; readM mnl (j - 1)
205          loopM_ (m - 1) (&gt;= 0) (subtract 1) $ \j -&gt; do
206            val &lt;- max (a ! ((ord ! i) :. j)) &lt;$&gt; readM mxr j
207            writeM mxr j val
208            when (j &lt; m - 1) $
209              writeM mxr j . max val =&lt;&lt; readM mxr (j + 1)
210          let goJ j
211                | j &lt; m - 1 = do
212                    mnlVal &lt;- readM mnl j
213                    mxlVal &lt;- readM mxl (i + 1 :. j)
214                    mxrVal &lt;- readM mxr (j + 1)
215                    mnrVal &lt;- readM mnr ((i + 1) :. (j + 1))
216                    if mnlVal &gt; mxlVal &amp;&amp; mxrVal &lt; mnrVal
217                      then pure $ Just (i, j)
218                      else goJ (j + 1)
219                | otherwise = pure Nothing
220          goJ 0 &gt;&gt;= \case
221            Nothing -&gt; goI (i + 1)
222            Just pair -&gt; pure $ Just pair
223        | otherwise = pure Nothing
224  mAns &lt;- goI 0
225  Control.Monad.forM mAns $ \ (ansFirst, ansSecond) -&gt; do
226    resVec &lt;- createArrayS_ @BL (Sz n) $ \res -&gt;
227        iforM_ ord $ \i ordIx -&gt; do
228          writeM res ordIx $! if i &lt;= ansFirst then R else B
229    pure (ansSecond + 1, A.toList resVec)
230

Source https://stackoverflow.com/questions/70143678

QUESTION

Typescript: deep keyof of a nested object, with related type

Asked 2021-Dec-02 at 09:30

I'm looking for a way to have all keys / values pair of a nested object.

(For the autocomplete of MongoDB dot notation key / value type)

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9

Here is what I want to achieve, to make it becomes:

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16
What I have tried:

In this answer, I can get the key with Leaves<IPerson>. So it becomes 'name' | 'age' | 'contact.address' | 'contact.visitDate'.

And in another answer from @jcalz, I can get the deep, related value type, with DeepIndex<IPerson, ...>.

Is it possible to group them together, to become type like TPerson?

Modified 9/14: The use cases, need and no need:

When I start this question, I was thinking it could be as easy as something like [K in keyof T]: T[K];, with some clever transformation. But I was wrong. Here is what I need:

1. Index Signature

So the interface

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22

becomes

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30

No need to check for valid number, the nature of Array / Index Signature should allow any number of elements.

2. Tuple

The interface

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33

becomes

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38

Tuple should be the one which cares about valid index numbers.

3. Readonly

readonly attributes should be removed from the final structure.

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43

becomes

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46

The use case is for MongoDB, the _id, _created_date cannot be modified after the data has been created. _id: never is not working in this case, since it will block the creation of TPerson.

4. Optional
1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52

becomes

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60

It's sufficient just to bring the optional flags to transformed structure.

5. Intersection
1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63

becomes

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68
6. Possible to Specify Types as Exception

The interface

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68interface IPerson {
69    birth: Date;
70}
71

becomes

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68interface IPerson {
69    birth: Date;
70}
71type TPerson = {
72    birth: Date;
73}
74

not

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68interface IPerson {
69    birth: Date;
70}
71type TPerson = {
72    birth: Date;
73}
74type TPerson = {
75    age: Date;
76    &quot;age.toDateString&quot;: () =&gt; string;
77    &quot;age.toTimeString&quot;: () =&gt; string;
78    &quot;age.toLocaleDateString&quot;: {
79    ...
80}
81

We can give a list of Types to be the end node.

Here is what I don't need:
  1. Union. It could be too complex with it.
  2. Class related keyword. No need to handle keywords ex: private / abstract .
  3. All the rest I didn't write it here.

ANSWER

Answered 2021-Dec-02 at 09:30

In order to achieve this goal we need to create permutation of all allowed paths. For example:

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68interface IPerson {
69    birth: Date;
70}
71type TPerson = {
72    birth: Date;
73}
74type TPerson = {
75    age: Date;
76    &quot;age.toDateString&quot;: () =&gt; string;
77    &quot;age.toTimeString&quot;: () =&gt; string;
78    &quot;age.toLocaleDateString&quot;: {
79    ...
80}
81type Structure = {
82    user: {
83        name: string,
84        surname: string
85    }
86}
87
88type BlackMagic&lt;T&gt;= T
89
90// user.name | user.surname
91type Result=BlackMagic&lt;Structure&gt;
92

Problem becomes more interesting with arrays and empty tuples.

Tuple, the array with explicit length, should be managed in this way:

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68interface IPerson {
69    birth: Date;
70}
71type TPerson = {
72    birth: Date;
73}
74type TPerson = {
75    age: Date;
76    &quot;age.toDateString&quot;: () =&gt; string;
77    &quot;age.toTimeString&quot;: () =&gt; string;
78    &quot;age.toLocaleDateString&quot;: {
79    ...
80}
81type Structure = {
82    user: {
83        name: string,
84        surname: string
85    }
86}
87
88type BlackMagic&lt;T&gt;= T
89
90// user.name | user.surname
91type Result=BlackMagic&lt;Structure&gt;
92type Structure = {
93    user: {
94        arr: [1, 2],
95    }
96}
97
98type BlackMagic&lt;T&gt; = T
99
100// &quot;user.arr&quot; | &quot;user.arr.0&quot; | &quot;user.arr.1&quot;
101type Result = BlackMagic&lt;Structure&gt;
102

Logic is straitforward. But how we can handle number[]? There is no guarantee that index 1 exists.

I have decided to use user.arr.${number}.

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68interface IPerson {
69    birth: Date;
70}
71type TPerson = {
72    birth: Date;
73}
74type TPerson = {
75    age: Date;
76    &quot;age.toDateString&quot;: () =&gt; string;
77    &quot;age.toTimeString&quot;: () =&gt; string;
78    &quot;age.toLocaleDateString&quot;: {
79    ...
80}
81type Structure = {
82    user: {
83        name: string,
84        surname: string
85    }
86}
87
88type BlackMagic&lt;T&gt;= T
89
90// user.name | user.surname
91type Result=BlackMagic&lt;Structure&gt;
92type Structure = {
93    user: {
94        arr: [1, 2],
95    }
96}
97
98type BlackMagic&lt;T&gt; = T
99
100// &quot;user.arr&quot; | &quot;user.arr.0&quot; | &quot;user.arr.1&quot;
101type Result = BlackMagic&lt;Structure&gt;
102type Structure = {
103    user: {
104        arr: number[],
105    }
106}
107
108type BlackMagic&lt;T&gt; = T
109
110// &quot;user.arr&quot; | `user.arr.${number}`
111type Result = BlackMagic&lt;Structure&gt;
112

We still have 1 problem. Empty tuple. Array with zero elements - []. Do we need to allow indexing at all? I don't know. I decided to use -1.

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68interface IPerson {
69    birth: Date;
70}
71type TPerson = {
72    birth: Date;
73}
74type TPerson = {
75    age: Date;
76    &quot;age.toDateString&quot;: () =&gt; string;
77    &quot;age.toTimeString&quot;: () =&gt; string;
78    &quot;age.toLocaleDateString&quot;: {
79    ...
80}
81type Structure = {
82    user: {
83        name: string,
84        surname: string
85    }
86}
87
88type BlackMagic&lt;T&gt;= T
89
90// user.name | user.surname
91type Result=BlackMagic&lt;Structure&gt;
92type Structure = {
93    user: {
94        arr: [1, 2],
95    }
96}
97
98type BlackMagic&lt;T&gt; = T
99
100// &quot;user.arr&quot; | &quot;user.arr.0&quot; | &quot;user.arr.1&quot;
101type Result = BlackMagic&lt;Structure&gt;
102type Structure = {
103    user: {
104        arr: number[],
105    }
106}
107
108type BlackMagic&lt;T&gt; = T
109
110// &quot;user.arr&quot; | `user.arr.${number}`
111type Result = BlackMagic&lt;Structure&gt;
112type Structure = {
113    user: {
114        arr: [],
115    }
116}
117
118type BlackMagic&lt;T&gt; = T
119
120//  &quot;user.arr&quot; | &quot;user.arr.-1&quot;
121type Result = BlackMagic&lt;Structure&gt;
122

I think the most important thing here is some convention. We can also use stringified `"never". I think it is up to OP how to handle it.

Since we know how we need to handle different cases we can start our implementation. Before we continue, we need to define several helpers.

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68interface IPerson {
69    birth: Date;
70}
71type TPerson = {
72    birth: Date;
73}
74type TPerson = {
75    age: Date;
76    &quot;age.toDateString&quot;: () =&gt; string;
77    &quot;age.toTimeString&quot;: () =&gt; string;
78    &quot;age.toLocaleDateString&quot;: {
79    ...
80}
81type Structure = {
82    user: {
83        name: string,
84        surname: string
85    }
86}
87
88type BlackMagic&lt;T&gt;= T
89
90// user.name | user.surname
91type Result=BlackMagic&lt;Structure&gt;
92type Structure = {
93    user: {
94        arr: [1, 2],
95    }
96}
97
98type BlackMagic&lt;T&gt; = T
99
100// &quot;user.arr&quot; | &quot;user.arr.0&quot; | &quot;user.arr.1&quot;
101type Result = BlackMagic&lt;Structure&gt;
102type Structure = {
103    user: {
104        arr: number[],
105    }
106}
107
108type BlackMagic&lt;T&gt; = T
109
110// &quot;user.arr&quot; | `user.arr.${number}`
111type Result = BlackMagic&lt;Structure&gt;
112type Structure = {
113    user: {
114        arr: [],
115    }
116}
117
118type BlackMagic&lt;T&gt; = T
119
120//  &quot;user.arr&quot; | &quot;user.arr.-1&quot;
121type Result = BlackMagic&lt;Structure&gt;
122type Values&lt;T&gt; = T[keyof T]
123{
124    // 1 | &quot;John&quot;
125    type _ = Values&lt;{ age: 1, name: 'John' }&gt;
126}
127
128type IsNever&lt;T&gt; = [T] extends [never] ? true : false;
129{
130    type _ = IsNever&lt;never&gt; // true 
131    type __ = IsNever&lt;true&gt; // false
132}
133
134type IsTuple&lt;T&gt; =
135    (T extends Array&lt;any&gt; ?
136        (T['length'] extends number
137            ? (number extends T['length']
138                ? false
139                : true)
140            : true)
141        : false)
142{
143    type _ = IsTuple&lt;[1, 2]&gt; // true
144    type __ = IsTuple&lt;number[]&gt; // false
145    type ___ = IsTuple&lt;{ length: 2 }&gt; // false
146}
147
148type IsEmptyTuple&lt;T extends Array&lt;any&gt;&gt; = T['length'] extends 0 ? true : false
149{
150    type _ = IsEmptyTuple&lt;[]&gt; // true
151    type __ = IsEmptyTuple&lt;[1]&gt; // false
152    type ___ = IsEmptyTuple&lt;number[]&gt; // false
153
154}
155

I think naming and tests are self explanatory. At least I want to believe :D

Now, when we have all set of our utils, we can define our main util:

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68interface IPerson {
69    birth: Date;
70}
71type TPerson = {
72    birth: Date;
73}
74type TPerson = {
75    age: Date;
76    &quot;age.toDateString&quot;: () =&gt; string;
77    &quot;age.toTimeString&quot;: () =&gt; string;
78    &quot;age.toLocaleDateString&quot;: {
79    ...
80}
81type Structure = {
82    user: {
83        name: string,
84        surname: string
85    }
86}
87
88type BlackMagic&lt;T&gt;= T
89
90// user.name | user.surname
91type Result=BlackMagic&lt;Structure&gt;
92type Structure = {
93    user: {
94        arr: [1, 2],
95    }
96}
97
98type BlackMagic&lt;T&gt; = T
99
100// &quot;user.arr&quot; | &quot;user.arr.0&quot; | &quot;user.arr.1&quot;
101type Result = BlackMagic&lt;Structure&gt;
102type Structure = {
103    user: {
104        arr: number[],
105    }
106}
107
108type BlackMagic&lt;T&gt; = T
109
110// &quot;user.arr&quot; | `user.arr.${number}`
111type Result = BlackMagic&lt;Structure&gt;
112type Structure = {
113    user: {
114        arr: [],
115    }
116}
117
118type BlackMagic&lt;T&gt; = T
119
120//  &quot;user.arr&quot; | &quot;user.arr.-1&quot;
121type Result = BlackMagic&lt;Structure&gt;
122type Values&lt;T&gt; = T[keyof T]
123{
124    // 1 | &quot;John&quot;
125    type _ = Values&lt;{ age: 1, name: 'John' }&gt;
126}
127
128type IsNever&lt;T&gt; = [T] extends [never] ? true : false;
129{
130    type _ = IsNever&lt;never&gt; // true 
131    type __ = IsNever&lt;true&gt; // false
132}
133
134type IsTuple&lt;T&gt; =
135    (T extends Array&lt;any&gt; ?
136        (T['length'] extends number
137            ? (number extends T['length']
138                ? false
139                : true)
140            : true)
141        : false)
142{
143    type _ = IsTuple&lt;[1, 2]&gt; // true
144    type __ = IsTuple&lt;number[]&gt; // false
145    type ___ = IsTuple&lt;{ length: 2 }&gt; // false
146}
147
148type IsEmptyTuple&lt;T extends Array&lt;any&gt;&gt; = T['length'] extends 0 ? true : false
149{
150    type _ = IsEmptyTuple&lt;[]&gt; // true
151    type __ = IsEmptyTuple&lt;[1]&gt; // false
152    type ___ = IsEmptyTuple&lt;number[]&gt; // false
153
154}
155/**
156 * If Cache is empty return Prop without dot,
157 * to avoid &quot;.user&quot;
158 */
159type HandleDot&lt;
160    Cache extends string,
161    Prop extends string | number
162    &gt; =
163    Cache extends ''
164    ? `${Prop}`
165    : `${Cache}.${Prop}`
166
167/**
168 * Simple iteration through object properties
169 */
170type HandleObject&lt;Obj, Cache extends string&gt; = {
171    [Prop in keyof Obj]:
172    // concat previous Cacha and Prop
173    | HandleDot&lt;Cache, Prop &amp; string&gt;
174    // with next Cache and Prop
175    | Path&lt;Obj[Prop], HandleDot&lt;Cache, Prop &amp; string&gt;&gt;
176}[keyof Obj]
177
178type Path&lt;Obj, Cache extends string = ''&gt; =
179    // if Obj is primitive
180    (Obj extends PropertyKey
181        // return Cache
182        ? Cache
183        // if Obj is Array (can be array, tuple, empty tuple)
184        : (Obj extends Array&lt;unknown&gt;
185            // and is tuple
186            ? (IsTuple&lt;Obj&gt; extends true
187                // and tuple is empty
188                ? (IsEmptyTuple&lt;Obj&gt; extends true
189                    // call recursively Path with `-1` as an allowed index
190                    ? Path&lt;PropertyKey, HandleDot&lt;Cache, -1&gt;&gt;
191                    // if tuple is not empty we can handle it as regular object
192                    : HandleObject&lt;Obj, Cache&gt;)
193                // if Obj is regular  array call Path with union of all elements
194                : Path&lt;Obj[number], HandleDot&lt;Cache, number&gt;&gt;)
195            // if Obj is neither Array nor Tuple nor Primitive - treat is as object    
196            : HandleObject&lt;Obj, Cache&gt;)
197    )
198
199// &quot;user&quot; | &quot;user.arr&quot; | `user.arr.${number}`
200type Test = Extract&lt;Path&lt;Structure&gt;, string&gt;
201

There is small issue. We should not return highest level props, like user. We need paths with at least one dot.

There are two ways:

  • extract all props without dots
  • provide extra generic parameter for indexing the level.

Two options are easy to implement.

Obtain all props with dot (.):

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68interface IPerson {
69    birth: Date;
70}
71type TPerson = {
72    birth: Date;
73}
74type TPerson = {
75    age: Date;
76    &quot;age.toDateString&quot;: () =&gt; string;
77    &quot;age.toTimeString&quot;: () =&gt; string;
78    &quot;age.toLocaleDateString&quot;: {
79    ...
80}
81type Structure = {
82    user: {
83        name: string,
84        surname: string
85    }
86}
87
88type BlackMagic&lt;T&gt;= T
89
90// user.name | user.surname
91type Result=BlackMagic&lt;Structure&gt;
92type Structure = {
93    user: {
94        arr: [1, 2],
95    }
96}
97
98type BlackMagic&lt;T&gt; = T
99
100// &quot;user.arr&quot; | &quot;user.arr.0&quot; | &quot;user.arr.1&quot;
101type Result = BlackMagic&lt;Structure&gt;
102type Structure = {
103    user: {
104        arr: number[],
105    }
106}
107
108type BlackMagic&lt;T&gt; = T
109
110// &quot;user.arr&quot; | `user.arr.${number}`
111type Result = BlackMagic&lt;Structure&gt;
112type Structure = {
113    user: {
114        arr: [],
115    }
116}
117
118type BlackMagic&lt;T&gt; = T
119
120//  &quot;user.arr&quot; | &quot;user.arr.-1&quot;
121type Result = BlackMagic&lt;Structure&gt;
122type Values&lt;T&gt; = T[keyof T]
123{
124    // 1 | &quot;John&quot;
125    type _ = Values&lt;{ age: 1, name: 'John' }&gt;
126}
127
128type IsNever&lt;T&gt; = [T] extends [never] ? true : false;
129{
130    type _ = IsNever&lt;never&gt; // true 
131    type __ = IsNever&lt;true&gt; // false
132}
133
134type IsTuple&lt;T&gt; =
135    (T extends Array&lt;any&gt; ?
136        (T['length'] extends number
137            ? (number extends T['length']
138                ? false
139                : true)
140            : true)
141        : false)
142{
143    type _ = IsTuple&lt;[1, 2]&gt; // true
144    type __ = IsTuple&lt;number[]&gt; // false
145    type ___ = IsTuple&lt;{ length: 2 }&gt; // false
146}
147
148type IsEmptyTuple&lt;T extends Array&lt;any&gt;&gt; = T['length'] extends 0 ? true : false
149{
150    type _ = IsEmptyTuple&lt;[]&gt; // true
151    type __ = IsEmptyTuple&lt;[1]&gt; // false
152    type ___ = IsEmptyTuple&lt;number[]&gt; // false
153
154}
155/**
156 * If Cache is empty return Prop without dot,
157 * to avoid &quot;.user&quot;
158 */
159type HandleDot&lt;
160    Cache extends string,
161    Prop extends string | number
162    &gt; =
163    Cache extends ''
164    ? `${Prop}`
165    : `${Cache}.${Prop}`
166
167/**
168 * Simple iteration through object properties
169 */
170type HandleObject&lt;Obj, Cache extends string&gt; = {
171    [Prop in keyof Obj]:
172    // concat previous Cacha and Prop
173    | HandleDot&lt;Cache, Prop &amp; string&gt;
174    // with next Cache and Prop
175    | Path&lt;Obj[Prop], HandleDot&lt;Cache, Prop &amp; string&gt;&gt;
176}[keyof Obj]
177
178type Path&lt;Obj, Cache extends string = ''&gt; =
179    // if Obj is primitive
180    (Obj extends PropertyKey
181        // return Cache
182        ? Cache
183        // if Obj is Array (can be array, tuple, empty tuple)
184        : (Obj extends Array&lt;unknown&gt;
185            // and is tuple
186            ? (IsTuple&lt;Obj&gt; extends true
187                // and tuple is empty
188                ? (IsEmptyTuple&lt;Obj&gt; extends true
189                    // call recursively Path with `-1` as an allowed index
190                    ? Path&lt;PropertyKey, HandleDot&lt;Cache, -1&gt;&gt;
191                    // if tuple is not empty we can handle it as regular object
192                    : HandleObject&lt;Obj, Cache&gt;)
193                // if Obj is regular  array call Path with union of all elements
194                : Path&lt;Obj[number], HandleDot&lt;Cache, number&gt;&gt;)
195            // if Obj is neither Array nor Tuple nor Primitive - treat is as object    
196            : HandleObject&lt;Obj, Cache&gt;)
197    )
198
199// &quot;user&quot; | &quot;user.arr&quot; | `user.arr.${number}`
200type Test = Extract&lt;Path&lt;Structure&gt;, string&gt;
201type WithDot&lt;T extends string&gt; = T extends `${string}.${string}` ? T : never
202

While above util is readable and maintainable, second one is a bit harder. We need to provide extra generic parameter in both Path and HandleObject. See this example taken from other question / article:

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68interface IPerson {
69    birth: Date;
70}
71type TPerson = {
72    birth: Date;
73}
74type TPerson = {
75    age: Date;
76    &quot;age.toDateString&quot;: () =&gt; string;
77    &quot;age.toTimeString&quot;: () =&gt; string;
78    &quot;age.toLocaleDateString&quot;: {
79    ...
80}
81type Structure = {
82    user: {
83        name: string,
84        surname: string
85    }
86}
87
88type BlackMagic&lt;T&gt;= T
89
90// user.name | user.surname
91type Result=BlackMagic&lt;Structure&gt;
92type Structure = {
93    user: {
94        arr: [1, 2],
95    }
96}
97
98type BlackMagic&lt;T&gt; = T
99
100// &quot;user.arr&quot; | &quot;user.arr.0&quot; | &quot;user.arr.1&quot;
101type Result = BlackMagic&lt;Structure&gt;
102type Structure = {
103    user: {
104        arr: number[],
105    }
106}
107
108type BlackMagic&lt;T&gt; = T
109
110// &quot;user.arr&quot; | `user.arr.${number}`
111type Result = BlackMagic&lt;Structure&gt;
112type Structure = {
113    user: {
114        arr: [],
115    }
116}
117
118type BlackMagic&lt;T&gt; = T
119
120//  &quot;user.arr&quot; | &quot;user.arr.-1&quot;
121type Result = BlackMagic&lt;Structure&gt;
122type Values&lt;T&gt; = T[keyof T]
123{
124    // 1 | &quot;John&quot;
125    type _ = Values&lt;{ age: 1, name: 'John' }&gt;
126}
127
128type IsNever&lt;T&gt; = [T] extends [never] ? true : false;
129{
130    type _ = IsNever&lt;never&gt; // true 
131    type __ = IsNever&lt;true&gt; // false
132}
133
134type IsTuple&lt;T&gt; =
135    (T extends Array&lt;any&gt; ?
136        (T['length'] extends number
137            ? (number extends T['length']
138                ? false
139                : true)
140            : true)
141        : false)
142{
143    type _ = IsTuple&lt;[1, 2]&gt; // true
144    type __ = IsTuple&lt;number[]&gt; // false
145    type ___ = IsTuple&lt;{ length: 2 }&gt; // false
146}
147
148type IsEmptyTuple&lt;T extends Array&lt;any&gt;&gt; = T['length'] extends 0 ? true : false
149{
150    type _ = IsEmptyTuple&lt;[]&gt; // true
151    type __ = IsEmptyTuple&lt;[1]&gt; // false
152    type ___ = IsEmptyTuple&lt;number[]&gt; // false
153
154}
155/**
156 * If Cache is empty return Prop without dot,
157 * to avoid &quot;.user&quot;
158 */
159type HandleDot&lt;
160    Cache extends string,
161    Prop extends string | number
162    &gt; =
163    Cache extends ''
164    ? `${Prop}`
165    : `${Cache}.${Prop}`
166
167/**
168 * Simple iteration through object properties
169 */
170type HandleObject&lt;Obj, Cache extends string&gt; = {
171    [Prop in keyof Obj]:
172    // concat previous Cacha and Prop
173    | HandleDot&lt;Cache, Prop &amp; string&gt;
174    // with next Cache and Prop
175    | Path&lt;Obj[Prop], HandleDot&lt;Cache, Prop &amp; string&gt;&gt;
176}[keyof Obj]
177
178type Path&lt;Obj, Cache extends string = ''&gt; =
179    // if Obj is primitive
180    (Obj extends PropertyKey
181        // return Cache
182        ? Cache
183        // if Obj is Array (can be array, tuple, empty tuple)
184        : (Obj extends Array&lt;unknown&gt;
185            // and is tuple
186            ? (IsTuple&lt;Obj&gt; extends true
187                // and tuple is empty
188                ? (IsEmptyTuple&lt;Obj&gt; extends true
189                    // call recursively Path with `-1` as an allowed index
190                    ? Path&lt;PropertyKey, HandleDot&lt;Cache, -1&gt;&gt;
191                    // if tuple is not empty we can handle it as regular object
192                    : HandleObject&lt;Obj, Cache&gt;)
193                // if Obj is regular  array call Path with union of all elements
194                : Path&lt;Obj[number], HandleDot&lt;Cache, number&gt;&gt;)
195            // if Obj is neither Array nor Tuple nor Primitive - treat is as object    
196            : HandleObject&lt;Obj, Cache&gt;)
197    )
198
199// &quot;user&quot; | &quot;user.arr&quot; | `user.arr.${number}`
200type Test = Extract&lt;Path&lt;Structure&gt;, string&gt;
201type WithDot&lt;T extends string&gt; = T extends `${string}.${string}` ? T : never
202type KeysUnion&lt;T, Cache extends string = '', Level extends any[] = []&gt; =
203  T extends PropertyKey ? Cache : {
204    [P in keyof T]:
205    P extends string
206    ? Cache extends ''
207    ? KeysUnion&lt;T[P], `${P}`, [...Level, 1]&gt;
208    : Level['length'] extends 1 // if it is a higher level - proceed
209    ? KeysUnion&lt;T[P], `${Cache}.${P}`, [...Level, 1]&gt;
210    : Level['length'] extends 2 // stop on second level
211    ? Cache | KeysUnion&lt;T[P], `${Cache}`, [...Level, 1]&gt;
212    : never
213    : never
214  }[keyof T]
215

Honestly, I don't think it will be easy for any one to read this.

We need to implement one more thing. We need to obtain a value by computed path.

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68interface IPerson {
69    birth: Date;
70}
71type TPerson = {
72    birth: Date;
73}
74type TPerson = {
75    age: Date;
76    &quot;age.toDateString&quot;: () =&gt; string;
77    &quot;age.toTimeString&quot;: () =&gt; string;
78    &quot;age.toLocaleDateString&quot;: {
79    ...
80}
81type Structure = {
82    user: {
83        name: string,
84        surname: string
85    }
86}
87
88type BlackMagic&lt;T&gt;= T
89
90// user.name | user.surname
91type Result=BlackMagic&lt;Structure&gt;
92type Structure = {
93    user: {
94        arr: [1, 2],
95    }
96}
97
98type BlackMagic&lt;T&gt; = T
99
100// &quot;user.arr&quot; | &quot;user.arr.0&quot; | &quot;user.arr.1&quot;
101type Result = BlackMagic&lt;Structure&gt;
102type Structure = {
103    user: {
104        arr: number[],
105    }
106}
107
108type BlackMagic&lt;T&gt; = T
109
110// &quot;user.arr&quot; | `user.arr.${number}`
111type Result = BlackMagic&lt;Structure&gt;
112type Structure = {
113    user: {
114        arr: [],
115    }
116}
117
118type BlackMagic&lt;T&gt; = T
119
120//  &quot;user.arr&quot; | &quot;user.arr.-1&quot;
121type Result = BlackMagic&lt;Structure&gt;
122type Values&lt;T&gt; = T[keyof T]
123{
124    // 1 | &quot;John&quot;
125    type _ = Values&lt;{ age: 1, name: 'John' }&gt;
126}
127
128type IsNever&lt;T&gt; = [T] extends [never] ? true : false;
129{
130    type _ = IsNever&lt;never&gt; // true 
131    type __ = IsNever&lt;true&gt; // false
132}
133
134type IsTuple&lt;T&gt; =
135    (T extends Array&lt;any&gt; ?
136        (T['length'] extends number
137            ? (number extends T['length']
138                ? false
139                : true)
140            : true)
141        : false)
142{
143    type _ = IsTuple&lt;[1, 2]&gt; // true
144    type __ = IsTuple&lt;number[]&gt; // false
145    type ___ = IsTuple&lt;{ length: 2 }&gt; // false
146}
147
148type IsEmptyTuple&lt;T extends Array&lt;any&gt;&gt; = T['length'] extends 0 ? true : false
149{
150    type _ = IsEmptyTuple&lt;[]&gt; // true
151    type __ = IsEmptyTuple&lt;[1]&gt; // false
152    type ___ = IsEmptyTuple&lt;number[]&gt; // false
153
154}
155/**
156 * If Cache is empty return Prop without dot,
157 * to avoid &quot;.user&quot;
158 */
159type HandleDot&lt;
160    Cache extends string,
161    Prop extends string | number
162    &gt; =
163    Cache extends ''
164    ? `${Prop}`
165    : `${Cache}.${Prop}`
166
167/**
168 * Simple iteration through object properties
169 */
170type HandleObject&lt;Obj, Cache extends string&gt; = {
171    [Prop in keyof Obj]:
172    // concat previous Cacha and Prop
173    | HandleDot&lt;Cache, Prop &amp; string&gt;
174    // with next Cache and Prop
175    | Path&lt;Obj[Prop], HandleDot&lt;Cache, Prop &amp; string&gt;&gt;
176}[keyof Obj]
177
178type Path&lt;Obj, Cache extends string = ''&gt; =
179    // if Obj is primitive
180    (Obj extends PropertyKey
181        // return Cache
182        ? Cache
183        // if Obj is Array (can be array, tuple, empty tuple)
184        : (Obj extends Array&lt;unknown&gt;
185            // and is tuple
186            ? (IsTuple&lt;Obj&gt; extends true
187                // and tuple is empty
188                ? (IsEmptyTuple&lt;Obj&gt; extends true
189                    // call recursively Path with `-1` as an allowed index
190                    ? Path&lt;PropertyKey, HandleDot&lt;Cache, -1&gt;&gt;
191                    // if tuple is not empty we can handle it as regular object
192                    : HandleObject&lt;Obj, Cache&gt;)
193                // if Obj is regular  array call Path with union of all elements
194                : Path&lt;Obj[number], HandleDot&lt;Cache, number&gt;&gt;)
195            // if Obj is neither Array nor Tuple nor Primitive - treat is as object    
196            : HandleObject&lt;Obj, Cache&gt;)
197    )
198
199// &quot;user&quot; | &quot;user.arr&quot; | `user.arr.${number}`
200type Test = Extract&lt;Path&lt;Structure&gt;, string&gt;
201type WithDot&lt;T extends string&gt; = T extends `${string}.${string}` ? T : never
202type KeysUnion&lt;T, Cache extends string = '', Level extends any[] = []&gt; =
203  T extends PropertyKey ? Cache : {
204    [P in keyof T]:
205    P extends string
206    ? Cache extends ''
207    ? KeysUnion&lt;T[P], `${P}`, [...Level, 1]&gt;
208    : Level['length'] extends 1 // if it is a higher level - proceed
209    ? KeysUnion&lt;T[P], `${Cache}.${P}`, [...Level, 1]&gt;
210    : Level['length'] extends 2 // stop on second level
211    ? Cache | KeysUnion&lt;T[P], `${Cache}`, [...Level, 1]&gt;
212    : never
213    : never
214  }[keyof T]
215
216type Acc = Record&lt;string, any&gt;
217
218type ReducerCallback&lt;Accumulator extends Acc, El extends string&gt; =
219    El extends keyof Accumulator ? Accumulator[El] : Accumulator
220
221type Reducer&lt;
222    Keys extends string,
223    Accumulator extends Acc = {}
224    &gt; =
225    // Key destructure
226    Keys extends `${infer Prop}.${infer Rest}`
227    // call Reducer with callback, just like in JS
228    ? Reducer&lt;Rest, ReducerCallback&lt;Accumulator, Prop&gt;&gt;
229    // this is the last part of path because no dot
230    : Keys extends `${infer Last}`
231    // call reducer with last part
232    ? ReducerCallback&lt;Accumulator, Last&gt;
233    : never
234
235{
236    type _ = Reducer&lt;'user.arr', Structure&gt; // []
237    type __ = Reducer&lt;'user', Structure&gt; // { arr: [] }
238}
239

You can find more information about using Reducein my blog.

Whole code:

1interface IPerson {
2    name: string;
3    age: number;
4    contact: {
5        address: string;
6        visitDate: Date;
7    }
8}
9type TPerson = {
10    name: string;
11    age: number;
12    contact: { address: string; visitDate: Date; }
13    &quot;contact.address&quot;: string;
14    &quot;contact.visitDate&quot;: Date;
15}
16interface IPerson {
17    contact: {
18        address: string;
19        visitDate: Date;
20    }[]
21}
22type TPerson = {
23    [x: `contact.${number}.address`]: string;
24    [x: `contact.${number}.visitDate`]: Date;
25    contact: {
26        address: string;
27        visitDate: Date;
28    }[];
29}
30interface IPerson {
31    contact: [string, Date]
32}
33type TPerson = {
34    [x: `contact.0`]: string;
35    [x: `contact.1`]: Date;
36    contact: [string, Date];
37}
38interface IPerson {
39    readonly _id: string;
40    age: number;
41    readonly _created_date: Date;
42}
43type TPerson = {
44    age: number;
45}
46interface IPerson {
47    contact: {
48        address: string;
49        visitDate?: Date;
50    }[];        
51}
52type TPerson = {
53    [x: `contact.${number}.address`]: string;
54    [x: `contact.${number}.visitDate`]?: Date;
55    contact: {
56        address: string;
57        visitDate?: Date;
58    }[];
59}
60interface IPerson {
61    contact: { address: string; } &amp; { visitDate: Date; }
62}
63type TPerson = {
64    [x: `contact.address`]: string;
65    [x: `contact.visitDate`]?: Date;
66    contact: { address: string; } &amp; { visitDate: Date; }
67}
68interface IPerson {
69    birth: Date;
70}
71type TPerson = {
72    birth: Date;
73}
74type TPerson = {
75    age: Date;
76    &quot;age.toDateString&quot;: () =&gt; string;
77    &quot;age.toTimeString&quot;: () =&gt; string;
78    &quot;age.toLocaleDateString&quot;: {
79    ...
80}
81type Structure = {
82    user: {
83        name: string,
84        surname: string
85    }
86}
87
88type BlackMagic&lt;T&gt;= T
89
90// user.name | user.surname
91type Result=BlackMagic&lt;Structure&gt;
92type Structure = {
93    user: {
94        arr: [1, 2],
95    }
96}
97
98type BlackMagic&lt;T&gt; = T
99
100// &quot;user.arr&quot; | &quot;user.arr.0&quot; | &quot;user.arr.1&quot;
101type Result = BlackMagic&lt;Structure&gt;
102type Structure = {
103    user: {
104        arr: number[],
105    }
106}
107
108type BlackMagic&lt;T&gt; = T
109
110// &quot;user.arr&quot; | `user.arr.${number}`
111type Result = BlackMagic&lt;Structure&gt;
112type Structure = {
113    user: {
114        arr: [],
115    }
116}
117
118type BlackMagic&lt;T&gt; = T
119
120//  &quot;user.arr&quot; | &quot;user.arr.-1&quot;
121type Result = BlackMagic&lt;Structure&gt;
122type Values&lt;T&gt; = T[keyof T]
123{
124    // 1 | &quot;John&quot;
125    type _ = Values&lt;{ age: 1, name: 'John' }&gt;
126}
127
128type IsNever&lt;T&gt; = [T] extends [never] ? true : false;
129{
130    type _ = IsNever&lt;never&gt; // true 
131    type __ = IsNever&lt;true&gt; // false
132}
133
134type IsTuple&lt;T&gt; =
135    (T extends Array&lt;any&gt; ?
136        (T['length'] extends number
137            ? (number extends T['length']
138                ? false
139                : true)
140            : true)
141        : false)
142{
143    type _ = IsTuple&lt;[1, 2]&gt; // true
144    type __ = IsTuple&lt;number[]&gt; // false
145    type ___ = IsTuple&lt;{ length: 2 }&gt; // false
146}
147
148type IsEmptyTuple&lt;T extends Array&lt;any&gt;&gt; = T['length'] extends 0 ? true : false
149{
150    type _ = IsEmptyTuple&lt;[]&gt; // true
151    type __ = IsEmptyTuple&lt;[1]&gt; // false
152    type ___ = IsEmptyTuple&lt;number[]&gt; // false
153
154}
155/**
156 * If Cache is empty return Prop without dot,
157 * to avoid &quot;.user&quot;
158 */
159type HandleDot&lt;
160    Cache extends string,
161    Prop extends string | number
162    &gt; =
163    Cache extends ''
164    ? `${Prop}`
165    : `${Cache}.${Prop}`
166
167/**
168 * Simple iteration through object properties
169 */
170type HandleObject&lt;Obj, Cache extends string&gt; = {
171    [Prop in keyof Obj]:
172    // concat previous Cacha and Prop
173    | HandleDot&lt;Cache, Prop &amp; string&gt;
174    // with next Cache and Prop
175    | Path&lt;Obj[Prop], HandleDot&lt;Cache, Prop &amp; string&gt;&gt;
176}[keyof Obj]
177
178type Path&lt;Obj, Cache extends string = ''&gt; =
179    // if Obj is primitive
180    (Obj extends PropertyKey
181        // return Cache
182        ? Cache
183        // if Obj is Array (can be array, tuple, empty tuple)
184        : (Obj extends Array&lt;unknown&gt;
185            // and is tuple
186            ? (IsTuple&lt;Obj&gt; extends true
187                // and tuple is empty
188                ? (IsEmptyTuple&lt;Obj&gt; extends true
189                    // call recursively Path with `-1` as an allowed index
190                    ? Path&lt;PropertyKey, HandleDot&lt;Cache, -1&gt;&gt;
191                    // if tuple is not empty we can handle it as regular object
192                    : HandleObject&lt;Obj, Cache&gt;)
193                // if Obj is regular  array call Path with union of all elements
194                : Path&lt;Obj[number], HandleDot&lt;Cache, number&gt;&gt;)
195            // if Obj is neither Array nor Tuple nor Primitive - treat is as object    
196            : HandleObject&lt;Obj, Cache&gt;)
197    )
198
199// &quot;user&quot; | &quot;user.arr&quot; | `user.arr.${number}`
200type Test = Extract&lt;Path&lt;Structure&gt;, string&gt;
201type WithDot&lt;T extends string&gt; = T extends `${string}.${string}` ? T : never
202type KeysUnion&lt;T, Cache extends string = '', Level extends any[] = []&gt; =
203  T extends PropertyKey ? Cache : {
204    [P in keyof T]:
205    P extends string
206    ? Cache extends ''
207    ? KeysUnion&lt;T[P], `${P}`, [...Level, 1]&gt;
208    : Level['length'] extends 1 // if it is a higher level - proceed
209    ? KeysUnion&lt;T[P], `${Cache}.${P}`, [...Level, 1]&gt;
210    : Level['length'] extends 2 // stop on second level
211    ? Cache | KeysUnion&lt;T[P], `${Cache}`, [...Level, 1]&gt;
212    : never
213    : never
214  }[keyof T]
215
216type Acc = Record&lt;string, any&gt;
217
218type ReducerCallback&lt;Accumulator extends Acc, El extends string&gt; =
219    El extends keyof Accumulator ? Accumulator[El] : Accumulator
220
221type Reducer&lt;
222    Keys extends string,
223    Accumulator extends Acc = {}
224    &gt; =
225    // Key destructure
226    Keys extends `${infer Prop}.${infer Rest}`
227    // call Reducer with callback, just like in JS
228    ? Reducer&lt;Rest, ReducerCallback&lt;Accumulator, Prop&gt;&gt;
229    // this is the last part of path because no dot
230    : Keys extends `${infer Last}`
231    // call reducer with last part
232    ? ReducerCallback&lt;Accumulator, Last&gt;
233    : never
234
235{
236    type _ = Reducer&lt;'user.arr', Structure&gt; // []
237    type __ = Reducer&lt;'user', Structure&gt; // { arr: [] }
238}
239type Structure = {
240    user: {
241        tuple: [42],
242        emptyTuple: [],
243        array: { age: number }[]
244    }
245}
246
247
248type Values&lt;T&gt; = T[keyof T]
249{
250    // 1 | &quot;John&quot;
251    type _ = Values&lt;{ age: 1, name: 'John' }&gt;
252}
253
254type IsNever&lt;T&gt; = [T] extends [never] ? true : false;
255{
256    type _ = IsNever&lt;never&gt; // true 
257    type __ = IsNever&lt;true&gt; // false
258}
259
260type IsTuple&lt;T&gt; =
261    (T extends Array&lt;any&gt; ?
262        (T['length'] extends number
263            ? (number extends T['length']
264                ? false
265                : true)
266            : true)
267        : false)
268{
269    type _ = IsTuple&lt;[1, 2]&gt; // true
270    type __ = IsTuple&lt;number[]&gt; // false
271    type ___ = IsTuple&lt;{ length: 2 }&gt; // false
272}
273
274type IsEmptyTuple&lt;T extends Array&lt;any&gt;&gt; = T['length'] extends 0 ? true : false
275{
276    type _ = IsEmptyTuple&lt;[]&gt; // true
277    type __ = IsEmptyTuple&lt;[1]&gt; // false
278    type ___ = IsEmptyTuple&lt;number[]&gt; // false
279}
280
281/**
282 * If Cache is empty return Prop without dot,
283 * to avoid &quot;.user&quot;
284 */
285type HandleDot&lt;
286    Cache extends string,
287    Prop extends string | number
288    &gt; =
289    Cache extends ''
290    ? `${Prop}`
291    : `${Cache}.${Prop}`
292
293/**
294 * Simple iteration through object properties
295 */
296type HandleObject&lt;Obj, Cache extends string&gt; = {
297    [Prop in keyof Obj]:
298    // concat previous Cacha and Prop
299    | HandleDot&lt;Cache, Prop &amp; string&gt;
300    // with next Cache and Prop
301    | Path&lt;Obj[Prop], HandleDot&lt;Cache, Prop &amp; string&gt;&gt;
302}[keyof Obj]
303
304type Path&lt;Obj, Cache extends string = ''&gt; =
305    (Obj extends PropertyKey
306        // return Cache
307        ? Cache
308        // if Obj is Array (can be array, tuple, empty tuple)
309        : (Obj extends Array&lt;unknown&gt;
310            // and is tuple
311            ? (IsTuple&lt;Obj&gt; extends true
312                // and tuple is empty
313                ? (IsEmptyTuple&lt;Obj&gt; extends true
314                    // call recursively Path with `-1` as an allowed index
315                    ? Path&lt;PropertyKey, HandleDot&lt;Cache, -1&gt;&gt;
316                    // if tuple is not empty we can handle it as regular object
317                    : HandleObject&lt;Obj, Cache&gt;)
318                // if Obj is regular  array call Path with union of all elements
319                : Path&lt;Obj[number], HandleDot&lt;Cache, number&gt;&gt;)
320            // if Obj is neither Array nor Tuple nor Primitive - treat is as object    
321            : HandleObject&lt;Obj, Cache&gt;)
322    )
323
324type WithDot&lt;T extends string&gt; = T extends `${string}.${string}` ? T : never
325
326
327// &quot;user&quot; | &quot;user.arr&quot; | `user.arr.${number}`
328type Test = WithDot&lt;Extract&lt;Path&lt;Structure&gt;, string&gt;&gt;
329
330
331
332type Acc = Record&lt;string, any&gt;
333
334type ReducerCallback&lt;Accumulator extends Acc, El extends string&gt; =
335    El extends keyof Accumulator ? Accumulator[El] : El extends '-1' ? never : Accumulator
336
337type Reducer&lt;
338    Keys extends string,
339    Accumulator extends Acc = {}
340    &gt; =
341    // Key destructure
342    Keys extends `${infer Prop}.${infer Rest}`
343    // call Reducer with callback, just like in JS
344    ? Reducer&lt;Rest, ReducerCallback&lt;Accumulator, Prop&gt;&gt;
345    // this is the last part of path because no dot
346    : Keys extends `${infer Last}`
347    // call reducer with last part
348    ? ReducerCallback&lt;Accumulator, Last&gt;
349    : never
350
351{
352    type _ = Reducer&lt;'user.arr', Structure&gt; // []
353    type __ = Reducer&lt;'user', Structure&gt; // { arr: [] }
354}
355
356type BlackMagic&lt;T&gt; = T &amp; {
357    [Prop in WithDot&lt;Extract&lt;Path&lt;T&gt;, string&gt;&gt;]: Reducer&lt;Prop, T&gt;
358}
359
360type Result = BlackMagic&lt;Structure&gt;
361

Playground

This implementation is worth considering

Source https://stackoverflow.com/questions/69126879

Community Discussions contain sources that include Stack Exchange Network

Tutorials and Learning Resources in REST

Tutorials and Learning Resources are not available at this moment for REST

Share this Page

share link

Get latest updates on REST