Тараненко Андрей, Холдинг Т1
Тараненко Андрей
Холдинг Т1
const capitalize = (str: string): string => {
return str.charAt(0).toUpperCase() + str.slice(1);
};
const capitalize = <T extends string>(str: T) => {
return (str.charAt(0).toUpperCase() + str.slice(1)) as Capitalize<T>;
};
const hello = 'hello';
const world = 'world';
const helloWorld = `${hello} ${world}!`;
const template = 'some string with [0] and [1]';
const text = interpolate(template, ['value1', 'value2']);
const template = 'some string with [first] and [second]';
const text = interpolate(template, { first: 'value1', second: 'value2' });
type GetInterpolatingVariablesNames<T extends string> =
T extends `${string}{{ ${infer Name} }}${infer Rest}`
? Name | GetInterpolatingVariablesNames<Rest>
: never;
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never;
type ConcatPath<Prefix extends string, Path extends string> = Prefix extends ""
? Path
: `${Prefix}.${Path}`;
type AnyResource = { [x: string]: string | AnyResource };
type FlattenResource<Resource extends AnyResource, Path extends string> = UnionToIntersection<
keyof Resource extends infer Keys extends keyof Resource
? Keys extends string
? Resource[Keys] extends AnyResource
? FlattenResource<Resource[Keys], ConcatPath<Path, Keys>>
: { [x in ConcatPath<Path, Keys>]: Resource[Keys] }
: never
: never
>;
type InterpolationParams<ResourceString extends string> =
GetInterpolatingVariablesNames<ResourceString> extends infer U extends string
? [U] extends [never]
? [param?: {}]
: [param: Record<U, string>]
: [param?: {}];
interface InterpolationMethod<FlatResource extends Record<string, string>> {
<Key extends keyof FlatResource | (string & {})>(
key: Key,
...[params]: InterpolationParams<FlatResource[Key]>
): Key extends keyof FlatResource ? string : null;
}
const helloWorld = 'Hello world !';
type HelloWorld = 'Hello world !';
type HelloWorld = 'Hello' | ' ' | 'world' | '!';
function myFunc(arg) {
return /* */;
}
type Generic<T> = {
payload: T;
};
type StringPayload = Generic<string>;
type Generic<T extends string> = /* */;
const getInterpolatingVariablesNames = (template) => {
const regExp = /{{ (?<name>.+) }}/g;
return template.matchAll(regExp);
}
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething(); doSomething();
type Generic<T> = Generic<T>
type IsString<T> = T extends string
? true
: false;
type Recursion<T> = T extends Condition
? Recursion<ChangeParam<T>>
: never;
type Name = 'world';
type Greet = `Hello ${Name}!`;
type Greet = 'Hello world!';
type Name = 'world' | 'Everyone';
type Greet = `Hello ${Name}!`;
type Greet = 'Hello world!' | 'Hello Everyone!';
type Greet = `Hello ${string}!`;
type HasValue<T> = T extends `{{ ${string} }}`
? true
: false
type Checked = HasValue<'Lorem, {{ name }} dolor'>; // false
type HasValue = 'Lorem, {{ name }} dolor' extends `${string}{{ ${string} }}${string}`
? true
: false
type HasValue = falsetype HasValue = true
type ArrayItem<T> = /* */;
type ArrayItem<T> = T extends any[]
? /* */
: never;
type ArrayItem<T> = T extends (infer U)[]
? U
: never;
type Checked = ArrayItem<number[]>; // number
type ArrayItem<T> = T extends (infer U extends string)[]
? U
: never;
type Checked = ArrayItem<number[]>; // never
type TupleItems<T extends [any, any]> = T extends [infer First, infer Second]
? First | Second
: never;
type Checked = TupleItems<[number, string]>; // number | string
type Generic<T> = GetNewType<T> extends infer U
? U
: never;
type Greet = 'Hello world!' extends `Hello ${infer U}!`
? U
: never;
type Greet = 'world'
type GetInterpolatingVariablesNames<T extends string> = /* */
type GetInterpolatingVariablesNames<T extends string> =
T extends /* */
? /* */
: never;
type GetInterpolatingVariablesNames<T extends string> =
T extends `{{ ${string} }}`
? /* */
: never;
type GetInterpolatingVariablesNames<T extends string> =
T extends `{{ ${infer Name} }}`
? Name
: never;
type GetInterpolatingVariablesNames<T extends string> =
T extends `${string}{{ ${infer Name} }}${string}`
? Name
: never;
type GetInterpolatingVariablesNames<T extends string> =
T extends `${string}{{ ${infer Name} }}${infer Rest}`
? Name | GetInterpolatingVariablesNames<Rest>
: never;
{
page: {
card: {
title: 'Title'
}
}
}
interpolate('page.card.title')
type AnyResource = {
[key: string]: string | AnyResource;
};
const concatPath = (prefix, path) => prefix ? `${prefix}.${path}` : path;
const flattenResource = (resource, path) => {
return Object.keys(resource)
.map((key) => {
if (typeof resource[key] === 'object') {
return flattenResource(resource[key], concatPath(path, key));
}
return { [concatPath(path, key)]: resource[key] };
})
.reduce((acc, obj) => ({ ...acc, ...obj }), {});
};
type HelloWorld = {
hello: "hello";
world: "world";
};
type Keys = keyof HelloWorld;
type Keys = 'hello' | 'world';
type HelloWorld = 'Hello' | 'World';
type Arr = HelloWorld[];
type Arr = ('Hello' | 'World')[];
type Arr = 'Hello'[] | 'World'[];
type Distributive<T> = T extends any ? T[] : never;
type ArraysUnion = Distributive<string | number>
type ArraysUnion = Distributive<string> | Distributive<number>
type ArraysUnion = string[] | number[]
type ArraysUnion = Distributive<never>
type ArraysUnion = never
type Distributive = 'Hello' | 'World' extends infer U
? U extends any
? U[]
: never
: never;
type Keys = 'hello' | 'world';
type Mapped = {
[Key in Keys]: Transform<Key>
}
type FunctionsUnion =
| ((arg: { hello: true }) => void)
| ((arg: { world: true }) => void);
type FunctionArgument = FunctionsUnion extends (arg: infer U) => void
? U
: never;
type FunctionArgument = OverloadedFunction extends (arg: infer U) => void
? U
: never;
type FunctionArgument = {
hello: true;
} & {
world: true;
};
type UnionToIntersection<U> = (
U extends unknown ? (k: U) => void : never
) extends (k: infer I) => void
? I
: never;
type First = { x: number };
type Second = { y: number };
type Point = UnionToIntersection<First | Second>;
type Point = { x: number; y: number };
type Check = UnionToIntersection<string | number>;
type ConcatPath<Prefix extends string, Path extends string> = /* */;
type ConcatPath<Prefix extends string, Path extends string> = /* */;
type FlattenResource<
Resource extends AnyResource,
Path extends string
> = /* */
type ConcatPath<Prefix extends string, Path extends string> = /* */;
type FlattenResource<
Resource extends AnyResource,
Path extends string
> = keyof Resource extends infer Keys extends keyof Resource
? Keys extends string
? /* */
: never
: never;
type ConcatPath<Prefix extends string, Path extends string> = /* */;
type FlattenResource<
Resource extends AnyResource,
Path extends string
> = keyof Resource extends infer Keys extends keyof Resource
? Keys extends string
? Resource[Keys] extends AnyResource
? /* */
: /* */
: never
: never;
type ConcatPath<Prefix extends string, Path extends string> = /* */;
type FlattenResource<
Resource extends AnyResource,
Path extends string
> = keyof Resource extends infer Keys extends keyof Resource
? Keys extends string
? Resource[Keys] extends AnyResource
? FlattenResource<Resource[Keys], ConcatPath<Path, Keys>>
: /* */
: never
: never;
type ConcatPath<Prefix extends string, Path extends string> = /* */;
type FlattenResource<
Resource extends AnyResource,
Path extends string
> = keyof Resource extends infer Keys extends keyof Resource
? Keys extends string
? Resource[Keys] extends AnyResource
? FlattenResource<Resource[Keys], ConcatPath<Path, Keys>>
: { [x in ConcatPath<Path, Keys>]: Resource[Keys] }
: never
: never;
type ConcatPath<Prefix extends string, Path extends string> = /* */;
type FlattenResource<
Resource extends AnyResource,
Path extends string
> = UnionToIntersection<
keyof Resource extends infer Keys extends keyof Resource
? Keys extends string
? Resource[Keys] extends AnyResource
? FlattenResource<Resource[Keys], ConcatPath<Path, Keys>>
: { [x in ConcatPath<Path, Keys>]: Resource[Keys] }
: never
: never
>;
type InterpolationParams<ResourceString extends string> = {/* */};
type InterpolationParams<ResourceString extends string> = {/* */};
interface InterpolationMethod<FlatResource extends Record<string, string>> {
<Key extends string>(
key: Key,
params: InterpolationParams<FlatResource[Key]>
): Key extends keyof FlatResource ? string : null;
}
const func = (...args: any[]) => /* */;
type Optional = [number?];
type NamedOptional = [param?: number];
type InterpolationParams<
ResourceString extends string,
> = GetInterpolatingVariablesNames<ResourceString> extends infer U
? [U] extends [never] // Важно из-за дистрибутивности
? [param?: {}]
: [param: Record<U, string>]
: never;
interface InterpolationMethod<FlatResource extends Record<string, string>> {
<Key extends string>( // Нет подсказок
key: Key,
...[params]: InterpolationParams<FlatResource[Key]>
): Key extends keyof FlatResource ? string : null;
}
interface InterpolationMethod<FlatResource extends Record<string, string>> {
<Key extends keyof FlatResource>(
key: Key,
...[params]: InterpolationParams<FlatResource[Key]>
): Key extends keyof FlatResource ? string : null;
}
type OrAnyString = 'hello' | 'world' | string
type OrAnyString = string 😢😢😢
type OrAnyString = 'hello' | 'world' | (string | {})
interface InterpolationMethod<FlatResource extends Record<string, string>> {
<Key extends keyof FlatResource | (string & {})>(
key: Key,
...[params]: InterpolationParams<FlatResource[Key]>
): Key extends keyof FlatResource ? string : null;
}
import { AnyResource, FlattenResource, InterpolationMethod } from "./types";
class Client<Resource extends AnyResource> {
constructor(private resource: Resource) {}
interpolate!: InterpolationMethod<FlattenResource<Resource, "">>;
}
Тараненко Андрей
Холдинг Т1