Remove unnecessary complex types (#7451)
#7290 introduced these types, but during development we switched over to specifying dependencies in type parameters instead of an object. This change meant we no longer needed these `Type` or `ShapeToInstance` types, greatly simplifying the types related to derived state.
This commit is contained in:
parent
5e11cb212d
commit
92f593df08
|
@ -3,15 +3,15 @@ import { Observable } from "rxjs";
|
||||||
import { DeriveDefinition, DerivedState } from "@bitwarden/common/platform/state";
|
import { DeriveDefinition, DerivedState } from "@bitwarden/common/platform/state";
|
||||||
// eslint-disable-next-line import/no-restricted-paths -- extending this class for this client
|
// eslint-disable-next-line import/no-restricted-paths -- extending this class for this client
|
||||||
import { DefaultDerivedStateProvider } from "@bitwarden/common/platform/state/implementations/default-derived-state.provider";
|
import { DefaultDerivedStateProvider } from "@bitwarden/common/platform/state/implementations/default-derived-state.provider";
|
||||||
import { ShapeToInstances, Type } from "@bitwarden/common/src/types/state";
|
import { DerivedStateDependencies } from "@bitwarden/common/src/types/state";
|
||||||
|
|
||||||
import { BackgroundDerivedState } from "./background-derived-state";
|
import { BackgroundDerivedState } from "./background-derived-state";
|
||||||
|
|
||||||
export class BackgroundDerivedStateProvider extends DefaultDerivedStateProvider {
|
export class BackgroundDerivedStateProvider extends DefaultDerivedStateProvider {
|
||||||
override buildDerivedState<TFrom, TTo, TDeps extends Record<string, Type<unknown>>>(
|
override buildDerivedState<TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
||||||
parentState$: Observable<TFrom>,
|
parentState$: Observable<TFrom>,
|
||||||
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
||||||
dependencies: ShapeToInstances<TDeps>,
|
dependencies: TDeps,
|
||||||
): DerivedState<TTo> {
|
): DerivedState<TTo> {
|
||||||
return new BackgroundDerivedState(
|
return new BackgroundDerivedState(
|
||||||
parentState$,
|
parentState$,
|
||||||
|
|
|
@ -9,14 +9,14 @@ import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { DeriveDefinition } from "@bitwarden/common/platform/state";
|
import { DeriveDefinition } from "@bitwarden/common/platform/state";
|
||||||
// eslint-disable-next-line import/no-restricted-paths -- extending this class for this client
|
// eslint-disable-next-line import/no-restricted-paths -- extending this class for this client
|
||||||
import { DefaultDerivedState } from "@bitwarden/common/platform/state/implementations/default-derived-state";
|
import { DefaultDerivedState } from "@bitwarden/common/platform/state/implementations/default-derived-state";
|
||||||
import { ShapeToInstances, Type } from "@bitwarden/common/types/state";
|
import { DerivedStateDependencies } from "@bitwarden/common/types/state";
|
||||||
|
|
||||||
import { BrowserApi } from "../browser/browser-api";
|
import { BrowserApi } from "../browser/browser-api";
|
||||||
|
|
||||||
export class BackgroundDerivedState<
|
export class BackgroundDerivedState<
|
||||||
TFrom,
|
TFrom,
|
||||||
TTo,
|
TTo,
|
||||||
TDeps extends Record<string, Type<unknown>>,
|
TDeps extends DerivedStateDependencies,
|
||||||
> extends DefaultDerivedState<TFrom, TTo, TDeps> {
|
> extends DefaultDerivedState<TFrom, TTo, TDeps> {
|
||||||
private portSubscriptions: Map<
|
private portSubscriptions: Map<
|
||||||
chrome.runtime.Port,
|
chrome.runtime.Port,
|
||||||
|
@ -27,7 +27,7 @@ export class BackgroundDerivedState<
|
||||||
parentState$: Observable<TFrom>,
|
parentState$: Observable<TFrom>,
|
||||||
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
||||||
memoryStorage: AbstractStorageService & ObservableStorageService,
|
memoryStorage: AbstractStorageService & ObservableStorageService,
|
||||||
dependencies: ShapeToInstances<TDeps>,
|
dependencies: TDeps,
|
||||||
) {
|
) {
|
||||||
super(parentState$, deriveDefinition, memoryStorage, dependencies);
|
super(parentState$, deriveDefinition, memoryStorage, dependencies);
|
||||||
const portName = deriveDefinition.buildCacheKey();
|
const portName = deriveDefinition.buildCacheKey();
|
||||||
|
|
|
@ -10,7 +10,6 @@ import { Subject, firstValueFrom } from "rxjs";
|
||||||
import { DeriveDefinition } from "@bitwarden/common/platform/state";
|
import { DeriveDefinition } from "@bitwarden/common/platform/state";
|
||||||
// eslint-disable-next-line import/no-restricted-paths -- needed to define a derive definition
|
// eslint-disable-next-line import/no-restricted-paths -- needed to define a derive definition
|
||||||
import { StateDefinition } from "@bitwarden/common/platform/state/state-definition";
|
import { StateDefinition } from "@bitwarden/common/platform/state/state-definition";
|
||||||
import { Type } from "@bitwarden/common/types/state";
|
|
||||||
|
|
||||||
import { mockPorts } from "../../../spec/mock-port.spec-util";
|
import { mockPorts } from "../../../spec/mock-port.spec-util";
|
||||||
|
|
||||||
|
@ -25,7 +24,7 @@ const deriveDefinition = new DeriveDefinition(stateDefinition, "test", {
|
||||||
|
|
||||||
describe("foreground background derived state interactions", () => {
|
describe("foreground background derived state interactions", () => {
|
||||||
let foreground: ForegroundDerivedState<Date>;
|
let foreground: ForegroundDerivedState<Date>;
|
||||||
let background: BackgroundDerivedState<string, Date, Record<string, Type<unknown>>>;
|
let background: BackgroundDerivedState<string, Date, Record<string, unknown>>;
|
||||||
let parentState$: Subject<string>;
|
let parentState$: Subject<string>;
|
||||||
let memoryStorage: FakeStorageService;
|
let memoryStorage: FakeStorageService;
|
||||||
const initialParent = "2020-01-01";
|
const initialParent = "2020-01-01";
|
||||||
|
|
|
@ -3,15 +3,15 @@ import { Observable } from "rxjs";
|
||||||
import { DeriveDefinition, DerivedState } from "@bitwarden/common/platform/state";
|
import { DeriveDefinition, DerivedState } from "@bitwarden/common/platform/state";
|
||||||
// eslint-disable-next-line import/no-restricted-paths -- extending this class for this client
|
// eslint-disable-next-line import/no-restricted-paths -- extending this class for this client
|
||||||
import { DefaultDerivedStateProvider } from "@bitwarden/common/platform/state/implementations/default-derived-state.provider";
|
import { DefaultDerivedStateProvider } from "@bitwarden/common/platform/state/implementations/default-derived-state.provider";
|
||||||
import { ShapeToInstances, Type } from "@bitwarden/common/src/types/state";
|
import { DerivedStateDependencies } from "@bitwarden/common/src/types/state";
|
||||||
|
|
||||||
import { ForegroundDerivedState } from "./foreground-derived-state";
|
import { ForegroundDerivedState } from "./foreground-derived-state";
|
||||||
|
|
||||||
export class ForegroundDerivedStateProvider extends DefaultDerivedStateProvider {
|
export class ForegroundDerivedStateProvider extends DefaultDerivedStateProvider {
|
||||||
override buildDerivedState<TFrom, TTo, TDeps extends Record<string, Type<unknown>>>(
|
override buildDerivedState<TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
||||||
_parentState$: Observable<TFrom>,
|
_parentState$: Observable<TFrom>,
|
||||||
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
||||||
_dependencies: ShapeToInstances<TDeps>,
|
_dependencies: TDeps,
|
||||||
): DerivedState<TTo> {
|
): DerivedState<TTo> {
|
||||||
return new ForegroundDerivedState(deriveDefinition);
|
return new ForegroundDerivedState(deriveDefinition);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
|
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { DeriveDefinition, DerivedState } from "@bitwarden/common/platform/state";
|
import { DeriveDefinition, DerivedState } from "@bitwarden/common/platform/state";
|
||||||
import { Type } from "@bitwarden/common/types/state";
|
import { DerivedStateDependencies } from "@bitwarden/common/types/state";
|
||||||
|
|
||||||
import { fromChromeEvent } from "../browser/from-chrome-event";
|
import { fromChromeEvent } from "../browser/from-chrome-event";
|
||||||
|
|
||||||
|
@ -23,9 +23,7 @@ export class ForegroundDerivedState<TTo> implements DerivedState<TTo> {
|
||||||
private backgroundResponses$: Observable<DerivedStateMessage>;
|
private backgroundResponses$: Observable<DerivedStateMessage>;
|
||||||
state$: Observable<TTo>;
|
state$: Observable<TTo>;
|
||||||
|
|
||||||
constructor(
|
constructor(private deriveDefinition: DeriveDefinition<unknown, TTo, DerivedStateDependencies>) {
|
||||||
private deriveDefinition: DeriveDefinition<unknown, TTo, Record<string, Type<unknown>>>,
|
|
||||||
) {
|
|
||||||
this.state$ = defer(() => this.initializePort()).pipe(
|
this.state$ = defer(() => this.initializePort()).pipe(
|
||||||
filter((message) => message.action === "nextState"),
|
filter((message) => message.action === "nextState"),
|
||||||
map((message) => this.hydrateNext(message.data)),
|
map((message) => this.hydrateNext(message.data)),
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {
|
||||||
DerivedStateProvider,
|
DerivedStateProvider,
|
||||||
} from "../src/platform/state";
|
} from "../src/platform/state";
|
||||||
import { UserId } from "../src/types/guid";
|
import { UserId } from "../src/types/guid";
|
||||||
import { ShapeToInstances, DerivedStateDependencies } from "../src/types/state";
|
import { DerivedStateDependencies } from "../src/types/state";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
FakeActiveUserState,
|
FakeActiveUserState,
|
||||||
|
@ -92,7 +92,7 @@ export class FakeStateProvider implements StateProvider {
|
||||||
getDerived<TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
getDerived<TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
||||||
parentState$: Observable<TFrom>,
|
parentState$: Observable<TFrom>,
|
||||||
deriveDefinition: DeriveDefinition<unknown, TTo, TDeps>,
|
deriveDefinition: DeriveDefinition<unknown, TTo, TDeps>,
|
||||||
dependencies: ShapeToInstances<TDeps>,
|
dependencies: TDeps,
|
||||||
): DerivedState<TTo> {
|
): DerivedState<TTo> {
|
||||||
return this.derived.get(parentState$, deriveDefinition, dependencies);
|
return this.derived.get(parentState$, deriveDefinition, dependencies);
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ export class FakeDerivedStateProvider implements DerivedStateProvider {
|
||||||
get<TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
get<TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
||||||
parentState$: Observable<TFrom>,
|
parentState$: Observable<TFrom>,
|
||||||
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
||||||
dependencies: ShapeToInstances<TDeps>,
|
dependencies: TDeps,
|
||||||
): DerivedState<TTo> {
|
): DerivedState<TTo> {
|
||||||
let result = this.states.get(deriveDefinition.buildCacheKey()) as DerivedState<TTo>;
|
let result = this.states.get(deriveDefinition.buildCacheKey()) as DerivedState<TTo>;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Jsonify } from "type-fest";
|
import { Jsonify } from "type-fest";
|
||||||
|
|
||||||
import { DerivedStateDependencies, ShapeToInstances, StorageKey } from "../../types/state";
|
import { DerivedStateDependencies, StorageKey } from "../../types/state";
|
||||||
|
|
||||||
import { KeyDefinition } from "./key-definition";
|
import { KeyDefinition } from "./key-definition";
|
||||||
import { StateDefinition } from "./state-definition";
|
import { StateDefinition } from "./state-definition";
|
||||||
|
@ -19,7 +19,7 @@ type DeriveDefinitionOptions<TFrom, TTo, TDeps extends DerivedStateDependencies
|
||||||
* These are constant for the lifetime of the derived state.
|
* These are constant for the lifetime of the derived state.
|
||||||
* @returns The derived state value or a Promise that resolves to the derived state value.
|
* @returns The derived state value or a Promise that resolves to the derived state value.
|
||||||
*/
|
*/
|
||||||
derive: (from: TFrom, deps: ShapeToInstances<TDeps>) => TTo | Promise<TTo>;
|
derive: (from: TFrom, deps: TDeps) => TTo | Promise<TTo>;
|
||||||
/**
|
/**
|
||||||
* A function to use to safely convert your type from json to your expected type.
|
* A function to use to safely convert your type from json to your expected type.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Observable } from "rxjs";
|
import { Observable } from "rxjs";
|
||||||
|
|
||||||
import { ShapeToInstances, DerivedStateDependencies } from "../../types/state";
|
import { DerivedStateDependencies } from "../../types/state";
|
||||||
|
|
||||||
import { DeriveDefinition } from "./derive-definition";
|
import { DeriveDefinition } from "./derive-definition";
|
||||||
import { DerivedState } from "./derived-state";
|
import { DerivedState } from "./derived-state";
|
||||||
|
@ -20,6 +20,6 @@ export abstract class DerivedStateProvider {
|
||||||
get: <TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
get: <TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
||||||
parentState$: Observable<TFrom>,
|
parentState$: Observable<TFrom>,
|
||||||
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
||||||
dependencies: ShapeToInstances<TDeps>,
|
dependencies: TDeps,
|
||||||
) => DerivedState<TTo>;
|
) => DerivedState<TTo>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Observable } from "rxjs";
|
import { Observable } from "rxjs";
|
||||||
|
|
||||||
import { DerivedStateDependencies, ShapeToInstances } from "../../../types/state";
|
import { DerivedStateDependencies } from "../../../types/state";
|
||||||
import {
|
import {
|
||||||
AbstractStorageService,
|
AbstractStorageService,
|
||||||
ObservableStorageService,
|
ObservableStorageService,
|
||||||
|
@ -19,7 +19,7 @@ export class DefaultDerivedStateProvider implements DerivedStateProvider {
|
||||||
get<TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
get<TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
||||||
parentState$: Observable<TFrom>,
|
parentState$: Observable<TFrom>,
|
||||||
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
||||||
dependencies: ShapeToInstances<TDeps>,
|
dependencies: TDeps,
|
||||||
): DerivedState<TTo> {
|
): DerivedState<TTo> {
|
||||||
const cacheKey = deriveDefinition.buildCacheKey();
|
const cacheKey = deriveDefinition.buildCacheKey();
|
||||||
const existingDerivedState = this.cache[cacheKey];
|
const existingDerivedState = this.cache[cacheKey];
|
||||||
|
@ -37,7 +37,7 @@ export class DefaultDerivedStateProvider implements DerivedStateProvider {
|
||||||
protected buildDerivedState<TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
protected buildDerivedState<TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
||||||
parentState$: Observable<TFrom>,
|
parentState$: Observable<TFrom>,
|
||||||
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
||||||
dependencies: ShapeToInstances<TDeps>,
|
dependencies: TDeps,
|
||||||
): DerivedState<TTo> {
|
): DerivedState<TTo> {
|
||||||
return new DefaultDerivedState<TFrom, TTo, TDeps>(
|
return new DefaultDerivedState<TFrom, TTo, TDeps>(
|
||||||
parentState$,
|
parentState$,
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { DefaultDerivedState } from "./default-derived-state";
|
||||||
let callCount = 0;
|
let callCount = 0;
|
||||||
const cleanupDelayMs = 10;
|
const cleanupDelayMs = 10;
|
||||||
const stateDefinition = new StateDefinition("test", "memory");
|
const stateDefinition = new StateDefinition("test", "memory");
|
||||||
const deriveDefinition = new DeriveDefinition<string, Date, { date: typeof Date }>(
|
const deriveDefinition = new DeriveDefinition<string, Date, { date: Date }>(
|
||||||
stateDefinition,
|
stateDefinition,
|
||||||
"test",
|
"test",
|
||||||
{
|
{
|
||||||
|
@ -30,7 +30,7 @@ const deriveDefinition = new DeriveDefinition<string, Date, { date: typeof Date
|
||||||
describe("DefaultDerivedState", () => {
|
describe("DefaultDerivedState", () => {
|
||||||
let parentState$: Subject<string>;
|
let parentState$: Subject<string>;
|
||||||
let memoryStorage: FakeStorageService;
|
let memoryStorage: FakeStorageService;
|
||||||
let sut: DefaultDerivedState<string, Date, { date: typeof Date }>;
|
let sut: DefaultDerivedState<string, Date, { date: Date }>;
|
||||||
const deps = {
|
const deps = {
|
||||||
date: new Date(),
|
date: new Date(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Observable, ReplaySubject, Subject, concatMap, merge, share, timer } from "rxjs";
|
import { Observable, ReplaySubject, Subject, concatMap, merge, share, timer } from "rxjs";
|
||||||
|
|
||||||
import { ShapeToInstances, DerivedStateDependencies } from "../../../types/state";
|
import { DerivedStateDependencies } from "../../../types/state";
|
||||||
import {
|
import {
|
||||||
AbstractStorageService,
|
AbstractStorageService,
|
||||||
ObservableStorageService,
|
ObservableStorageService,
|
||||||
|
@ -23,7 +23,7 @@ export class DefaultDerivedState<TFrom, TTo, TDeps extends DerivedStateDependenc
|
||||||
private parentState$: Observable<TFrom>,
|
private parentState$: Observable<TFrom>,
|
||||||
protected deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
protected deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
||||||
private memoryStorage: AbstractStorageService & ObservableStorageService,
|
private memoryStorage: AbstractStorageService & ObservableStorageService,
|
||||||
private dependencies: ShapeToInstances<TDeps>,
|
private dependencies: TDeps,
|
||||||
) {
|
) {
|
||||||
this.storageKey = deriveDefinition.storageKey;
|
this.storageKey = deriveDefinition.storageKey;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Observable } from "rxjs";
|
import { Observable } from "rxjs";
|
||||||
|
|
||||||
import { ShapeToInstances, DerivedStateDependencies } from "../../../types/state";
|
import { DerivedStateDependencies } from "../../../types/state";
|
||||||
import { DeriveDefinition } from "../derive-definition";
|
import { DeriveDefinition } from "../derive-definition";
|
||||||
import { DerivedState } from "../derived-state";
|
import { DerivedState } from "../derived-state";
|
||||||
import { DerivedStateProvider } from "../derived-state.provider";
|
import { DerivedStateProvider } from "../derived-state.provider";
|
||||||
|
@ -26,6 +26,6 @@ export class DefaultStateProvider implements StateProvider {
|
||||||
getDerived: <TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
getDerived: <TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
||||||
parentState$: Observable<TFrom>,
|
parentState$: Observable<TFrom>,
|
||||||
deriveDefinition: DeriveDefinition<unknown, TTo, TDeps>,
|
deriveDefinition: DeriveDefinition<unknown, TTo, TDeps>,
|
||||||
dependencies: ShapeToInstances<TDeps>,
|
dependencies: TDeps,
|
||||||
) => DerivedState<TTo> = this.derivedStateProvider.get.bind(this.derivedStateProvider);
|
) => DerivedState<TTo> = this.derivedStateProvider.get.bind(this.derivedStateProvider);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Observable } from "rxjs";
|
import { Observable } from "rxjs";
|
||||||
|
|
||||||
import { UserId } from "../../types/guid";
|
import { UserId } from "../../types/guid";
|
||||||
import { ShapeToInstances, DerivedStateDependencies } from "../../types/state";
|
import { DerivedStateDependencies } from "../../types/state";
|
||||||
|
|
||||||
import { DeriveDefinition } from "./derive-definition";
|
import { DeriveDefinition } from "./derive-definition";
|
||||||
import { DerivedState } from "./derived-state";
|
import { DerivedState } from "./derived-state";
|
||||||
|
@ -26,6 +26,6 @@ export abstract class StateProvider {
|
||||||
getDerived: <TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
getDerived: <TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
||||||
parentState$: Observable<TFrom>,
|
parentState$: Observable<TFrom>,
|
||||||
deriveDefinition: DeriveDefinition<unknown, TTo, TDeps>,
|
deriveDefinition: DeriveDefinition<unknown, TTo, TDeps>,
|
||||||
dependencies: ShapeToInstances<TDeps>,
|
dependencies: TDeps,
|
||||||
) => DerivedState<TTo>;
|
) => DerivedState<TTo>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,4 @@ import { Opaque } from "type-fest";
|
||||||
|
|
||||||
type StorageKey = Opaque<string, "StorageKey">;
|
type StorageKey = Opaque<string, "StorageKey">;
|
||||||
|
|
||||||
/**
|
type DerivedStateDependencies = Record<string, unknown>;
|
||||||
* A helper type defining Constructor types for javascript and `typeof T` types for Typescript
|
|
||||||
*/
|
|
||||||
type Type<T> = abstract new (...args: unknown[]) => T;
|
|
||||||
|
|
||||||
type DerivedStateDependencies = Record<string, Type<unknown>>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts an object of types to an object of instances
|
|
||||||
*/
|
|
||||||
type ShapeToInstances<T> = {
|
|
||||||
[P in keyof T]: T[P] extends Type<infer R> ? R : never;
|
|
||||||
};
|
|
||||||
|
|
Loading…
Reference in New Issue