Second argument of string.replace() 
String.prototype.replace() - JavaScript | MDN
The string.replace() method's second argument can be a function(replacer) instead of a string, and the function's return value will be used as the replacement string.
transitionend event are triggered frequently 
In the following code, the transitionend event is triggered 4 times each time the animation end:
<html>
<div class="ball"></div>
<style>
  .ball:hover {
	transform: scale(1.5);
	border-radius: 50%;
  }
</style>
<script>
  const ball = document.querySelector('.ball');
  ball.addEventListener('transitionend', () => {
	console.log('transition end');
  });
</script>
</html>Because the transitionend event is triggered when every CSS property transformation is completed, and the border-radius property actually contains 4 different CSS properties.
This problem can be solved by using the throttle function.
Using the infer to receive type in TS 
TypeScript: Documentation - Conditional Types The infer keyword in TS can be used to obtain one of the received types, just like this:
type GetParamReturnUnionType<Type> = Type extends (...args: (infer Param)[]) => infer Return
  ? Return | Param
  : never;
type Num = GetParamReturnUnionType<() => number>;
//  ^?type Num = number
type StrOrNumber = GetParamReturnUnionType<(x: number) => string>;
//   ^?type Str = string | number
type BoolsOrBool = GetParamReturnUnionType<(a: boolean, b: boolean) => boolean[]>;
//   ^?type BoolsOrBool = boolean | boolean[]Register custom CSS property 
Using the CSS properties and values API - Web APIs | MDN This is a new API can be used to register custom CSS property like this:
@property --registered {
  syntax: "<color>";
  inherits: false;
  initial-value: #c0ffee;
}
.registered {
  --registered: #c0ffee;
  background-image: linear-gradient(to right, #fff, var(--registered));
  transition: --registered 1s ease-in-out;
}
.registered:hover,
.registered:focus {
  --registered: #b4d455;
}This custom CSS property can be transformed using transition