') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - Derstilon/type-challenges: Collection of TypeScript type challenges with online judge · GitHub
Skip to content

Repository files navigation

Collection of TypeScript type challenges


English | 简体中文 | 日本語 | 한국어

Intro

by the power of TypeScript's well-known Turing Completed type system

High-quality types can help improve projects' maintainability while avoiding potential bugs.

There are a bunch of awesome type utility libraries that may boost your works on types, like ts-toolbelt, utility-types, SimplyTyped, etc., which you can already use.

This project is aimed at helping you better understand how the type system works, writing your own utilities, or just having fun with the challenges. We are also trying to form a community where you can ask questions and get answers you have faced in the real world - they may become part of the challenges!

Challenges

Click the following badges to see details of the challenges.

Note: Challenges work in the strict mode.


1
13・Hello World

13
4・Pick7・Readonly11・Tuple to Object14・First of Array18・Length of Tuple43・Exclude189・Awaited268・If533・Concat898・Includes3057・Push3060・Unshift3312・Parameters

78
2・Get Return Type3・Omit8・Readonly 29・Deep Readonly10・Tuple to Union12・Chainable Options15・Last of Array16・Pop20・Promise.all62・Type Lookup106・Trim Left108・Trim110・Capitalize116・Replace119・ReplaceAll191・Append Argument296・Permutation298・Length of String459・Flatten527・Append to object529・Absolute531・String to Union599・Merge612・KebabCase645・Diff949・AnyOf1042・IsNever1097・IsUnion1130・ReplaceKeys1367・Remove Index Signature1978・Percentage Parser2070・Drop Char2257・MinusOne2595・PickByType2688・StartsWith2693・EndsWith2757・PartialByKeys2759・RequiredByKeys2793・Mutable2852・OmitByType2946・ObjectEntries3062・Shift3188・Tuple to Nested Object3192・Reverse3196・Flip Arguments3243・FlattenDepth3326・BEM style string3376・InorderTraversal4179・Flip4182・Fibonacci Sequence4260・AllCombinations4425・Greater Than4471・Zip4484・IsTuple4499・Chunk4518・Fill4803・Trim Right5117・Without5140・Trunc5153・IndexOf5310・Join5317・LastIndexOf5360・Unique5821・MapTypes7544・Construct Tuple8640・Number Range8767・Combination8987・Subsequence9142・CheckRepeatedChars9286・FirstUniqueCharIndex9896・GetMiddleElement9898・Appear only once10969・Integer16259・ToPrimitive17973・DeepMutable18142・All18220・Filter21106・Combination key type

44
6・Simple Vue17・Currying 155・Union to Intersection57・Get Required59・Get Optional89・Required Keys90・Optional Keys112・Capitalize Words114・CamelCase147・C-printf Parser213・Vue Basic Props223・IsAny270・Typed Get300・String to Number399・Tuple Filter472・Tuple to Enum Object545・printf553・Deep object to unique651・Length of String 2730・Union to Tuple847・String Join956・DeepPick1290・Pinia1383・Camelize2059・Drop String2822・Split2828・ClassPublicKeys2857・IsRequiredKey2949・ObjectFromEntries4037・IsPalindrome5181・Mutable Keys5423・Intersection6141・Binary to Decimal7258・Object Key Paths8804・Two Sum9155・ValidDate9160・Assign9384・Maximum9775・Capitalize Nest Object Keys13580・Replace Union14080・FizzBuzz14188・Run-length encoding15260・Tree path array19458・SnakeCase

14
5・Get Readonly Keys151・Query String Parser216・Slice274・Integers Comparator462・Currying 2476・Sum517・Multiply697・Tag734・Inclusive Range741・Sort869・DistributeUnions925・Assert Array Index6228・JSON Parser7561・Subtract

By Tags
#application12・Chainable Options8767・Combination6・Simple Vue213・Vue Basic Props
#arguments191・Append Argument3196・Flip Arguments
#array14・First of Array533・Concat898・Includes3057・Push3060・Unshift15・Last of Array16・Pop20・Promise.all459・Flatten949・AnyOf3062・Shift3243・FlattenDepth4425・Greater Than5117・Without5153・IndexOf5310・Join5317・LastIndexOf5360・Unique8767・Combination18142・All18220・Filter17・Currying 12822・Split5423・Intersection8804・Two Sum9160・Assign9384・Maximum9775・Capitalize Nest Object Keys14080・FizzBuzz216・Slice734・Inclusive Range741・Sort925・Assert Array Index
#built-in4・Pick7・Readonly43・Exclude189・Awaited3312・Parameters2・Get Return Type3・Omit
#deep9・Deep Readonly553・Deep object to unique956・DeepPick
#filter18220・Filter
#infer3312・Parameters2・Get Return Type10・Tuple to Union2070・Drop Char4260・AllCombinations55・Union to Intersection57・Get Required59・Get Optional399・Tuple Filter730・Union to Tuple2059・Drop String14080・FizzBuzz734・Inclusive Range741・Sort
#json6228・JSON Parser
#map62・Type Lookup5821・MapTypes
#math529・Absolute2257・MinusOne6141・Binary to Decimal8804・Two Sum14080・FizzBuzz274・Integers Comparator476・Sum517・Multiply
#object599・Merge645・Diff2595・PickByType2757・PartialByKeys2759・RequiredByKeys2852・OmitByType2946・ObjectEntries3188・Tuple to Nested Object3376・InorderTraversal4179・Flip5821・MapTypes2949・ObjectFromEntries9160・Assign9775・Capitalize Nest Object Keys
#object-keys7・Readonly11・Tuple to Object8・Readonly 29・Deep Readonly527・Append to object1130・ReplaceKeys1367・Remove Index Signature2793・Mutable7258・Object Key Paths5・Get Readonly Keys
#promise189・Awaited20・Promise.all
#readonly7・Readonly8・Readonly 29・Deep Readonly2793・Mutable17973・DeepMutable
#recursion1383・Camelize
#split2822・Split
#string531・String to Union8767・Combination9142・CheckRepeatedChars9286・FirstUniqueCharIndex2822・Split4037・IsPalindrome19458・SnakeCase
#template-literal106・Trim Left108・Trim110・Capitalize116・Replace119・ReplaceAll298・Length of String529・Absolute612・KebabCase1978・Percentage Parser2070・Drop Char2688・StartsWith2693・EndsWith3326・BEM style string4260・AllCombinations4803・Trim Right5140・Trunc10969・Integer112・Capitalize Words114・CamelCase147・C-printf Parser270・Typed Get300・String to Number472・Tuple to Enum Object545・printf651・Length of String 22059・Drop String19458・SnakeCase151・Query String Parser274・Integers Comparator476・Sum517・Multiply6228・JSON Parser
#this6・Simple Vue1290・Pinia
#tuple18・Length of Tuple3312・Parameters10・Tuple to Union3188・Tuple to Nested Object3192・Reverse3326・BEM style string4471・Zip4484・IsTuple4499・Chunk4518・Fill7544・Construct Tuple399・Tuple Filter472・Tuple to Enum Object730・Union to Tuple2822・Split7561・Subtract
#union4・Pick43・Exclude3・Omit10・Tuple to Union62・Type Lookup296・Permutation531・String to Union1042・IsNever1097・IsUnion3326・BEM style string4260・AllCombinations5117・Without8987・Subsequence9142・CheckRepeatedChars730・Union to Tuple1383・Camelize5423・Intersection
#utils268・If1042・IsNever5821・MapTypes55・Union to Intersection57・Get Required59・Get Optional89・Required Keys90・Optional Keys223・IsAny270・Typed Get2828・ClassPublicKeys2857・IsRequiredKey5181・Mutable Keys5・Get Readonly Keys
#vue6・Simple Vue213・Vue Basic Props1290・Pinia

By Plain Text

warm-up (1)

easy (13)

medium (78)

hard (44)

extreme (14)


Upcoming challenges

🔥 Start the challenge in TypeScript Playground

🚀 Start the challenge locally in your IDE or text editor with TypeScript language support

⚡️ Start the challenge in VS Code Extension

Recommended Readings

Official

Articles

Talks

Projects / Solutions

Books

How to Contribute

There are several ways you can contribute to this project

  • Share your answers / solutions
  • Propose new challenges
  • Add more test cases to the existing challenges
  • Provide learning resources or ideas of how to solve challenges
  • Share the problems you have faced in real-world projects, regardless you having the solution or not - the community would help you as well
  • Help with others by discussion in issues
  • Contribute the infra of this project TODOs.md

Just open an issue and choose the corresponding template. Thanks!

Play Locally

You can build the challenges and play locally using your preferred IDE or text editor with TypeScript language support.

To do that, you will need the latest version of Node.js and pnpm installed.

After cloning the repo, installed the dependencies by:

pnpm install

Then and run the generate script:

pnpm generate

It will prompt you to select the desired language, then you can find the generated challenges in the ./playground folder.

Thanks

This project was born from solving real-world types problem with @hardfist and @MeCKodo. And great thanks to @sinoon who contributed a lot while giving early feedback on this project.

Inspired by

Contributors

License

MIT

About

Collection of TypeScript type challenges with online judge

Resources

Code of conduct

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages