Narrow destructured variables based on initializer's analysis result
This PR introduces a method to narrow the types of destructured variables through control flow analysis without relying on the discriminant member. When the initializer of the `ObjectBindingPattern` is available, we attempt to narrow its type, which in turn helps further refine the type of the destructured variable. Partially fixes #59657
This commit is contained in:
Родитель
a86b5e2b01
Коммит
77cb42b3d5
|
@ -30286,7 +30286,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
links.flags &= ~NodeCheckFlags.InCheckIdentifier;
|
||||
if (parentTypeConstraint && parentTypeConstraint.flags & TypeFlags.Union && !(rootDeclaration.kind === SyntaxKind.Parameter && isSomeSymbolAssigned(rootDeclaration))) {
|
||||
const pattern = declaration.parent;
|
||||
const narrowedType = getFlowTypeOfReference(pattern, parentTypeConstraint, parentTypeConstraint, /*flowContainer*/ undefined, location.flowNode);
|
||||
const initialType = parent.initializer
|
||||
? getFlowTypeOfReference(parent.initializer, parentTypeConstraint, parentTypeConstraint, /*flowContainer*/ undefined, location.flowNode)
|
||||
: parentTypeConstraint;
|
||||
const narrowedType = getFlowTypeOfReference(pattern, parentTypeConstraint, initialType, /*flowContainer*/ undefined, location.flowNode);
|
||||
if (narrowedType.flags & TypeFlags.Never) {
|
||||
return neverType;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
//// [tests/cases/compiler/narrowDestructuredVariables.ts] ////
|
||||
|
||||
//// [narrowDestructuredVariables.ts]
|
||||
interface Ref<T> { current: T };
|
||||
type ToRefs<T> = { [K in keyof T]: Ref<T[K]> };
|
||||
declare function toRefs<T>(o: T): ToRefs<T>;
|
||||
|
||||
interface DataPrepared {
|
||||
prepared: true
|
||||
payload: string
|
||||
};
|
||||
|
||||
interface DataPending {
|
||||
prepared: false
|
||||
payload: null
|
||||
};
|
||||
|
||||
type Data = DataPrepared | DataPending;
|
||||
|
||||
declare function isDataRefsPrepared(refs: ToRefs<Data>): refs is ToRefs<DataPrepared>;
|
||||
|
||||
declare const data: Data;
|
||||
const dataRefs = toRefs(data);
|
||||
const { prepared, payload } = dataRefs;
|
||||
|
||||
if (prepared.current) {
|
||||
prepared.current;
|
||||
payload.current;
|
||||
data.prepared;
|
||||
data.payload;
|
||||
}
|
||||
|
||||
if (isDataRefsPrepared(dataRefs)) {
|
||||
prepared.current;
|
||||
payload.current;
|
||||
data.prepared;
|
||||
data.payload;
|
||||
}
|
||||
|
||||
if (data.prepared) {
|
||||
prepared.current;
|
||||
payload.current;
|
||||
data.prepared;
|
||||
data.payload;
|
||||
}
|
||||
|
||||
|
||||
//// [narrowDestructuredVariables.js]
|
||||
"use strict";
|
||||
;
|
||||
;
|
||||
;
|
||||
const dataRefs = toRefs(data);
|
||||
const { prepared, payload } = dataRefs;
|
||||
if (prepared.current) {
|
||||
prepared.current;
|
||||
payload.current;
|
||||
data.prepared;
|
||||
data.payload;
|
||||
}
|
||||
if (isDataRefsPrepared(dataRefs)) {
|
||||
prepared.current;
|
||||
payload.current;
|
||||
data.prepared;
|
||||
data.payload;
|
||||
}
|
||||
if (data.prepared) {
|
||||
prepared.current;
|
||||
payload.current;
|
||||
data.prepared;
|
||||
data.payload;
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
//// [tests/cases/compiler/narrowDestructuredVariables.ts] ////
|
||||
|
||||
=== narrowDestructuredVariables.ts ===
|
||||
interface Ref<T> { current: T };
|
||||
>Ref : Symbol(Ref, Decl(narrowDestructuredVariables.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(narrowDestructuredVariables.ts, 0, 14))
|
||||
>current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
>T : Symbol(T, Decl(narrowDestructuredVariables.ts, 0, 14))
|
||||
|
||||
type ToRefs<T> = { [K in keyof T]: Ref<T[K]> };
|
||||
>ToRefs : Symbol(ToRefs, Decl(narrowDestructuredVariables.ts, 0, 32))
|
||||
>T : Symbol(T, Decl(narrowDestructuredVariables.ts, 1, 12))
|
||||
>K : Symbol(K, Decl(narrowDestructuredVariables.ts, 1, 20))
|
||||
>T : Symbol(T, Decl(narrowDestructuredVariables.ts, 1, 12))
|
||||
>Ref : Symbol(Ref, Decl(narrowDestructuredVariables.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(narrowDestructuredVariables.ts, 1, 12))
|
||||
>K : Symbol(K, Decl(narrowDestructuredVariables.ts, 1, 20))
|
||||
|
||||
declare function toRefs<T>(o: T): ToRefs<T>;
|
||||
>toRefs : Symbol(toRefs, Decl(narrowDestructuredVariables.ts, 1, 47))
|
||||
>T : Symbol(T, Decl(narrowDestructuredVariables.ts, 2, 24))
|
||||
>o : Symbol(o, Decl(narrowDestructuredVariables.ts, 2, 27))
|
||||
>T : Symbol(T, Decl(narrowDestructuredVariables.ts, 2, 24))
|
||||
>ToRefs : Symbol(ToRefs, Decl(narrowDestructuredVariables.ts, 0, 32))
|
||||
>T : Symbol(T, Decl(narrowDestructuredVariables.ts, 2, 24))
|
||||
|
||||
interface DataPrepared {
|
||||
>DataPrepared : Symbol(DataPrepared, Decl(narrowDestructuredVariables.ts, 2, 44))
|
||||
|
||||
prepared: true
|
||||
>prepared : Symbol(DataPrepared.prepared, Decl(narrowDestructuredVariables.ts, 4, 24))
|
||||
|
||||
payload: string
|
||||
>payload : Symbol(DataPrepared.payload, Decl(narrowDestructuredVariables.ts, 5, 18))
|
||||
|
||||
};
|
||||
|
||||
interface DataPending {
|
||||
>DataPending : Symbol(DataPending, Decl(narrowDestructuredVariables.ts, 7, 2))
|
||||
|
||||
prepared: false
|
||||
>prepared : Symbol(DataPending.prepared, Decl(narrowDestructuredVariables.ts, 9, 23))
|
||||
|
||||
payload: null
|
||||
>payload : Symbol(DataPending.payload, Decl(narrowDestructuredVariables.ts, 10, 19))
|
||||
|
||||
};
|
||||
|
||||
type Data = DataPrepared | DataPending;
|
||||
>Data : Symbol(Data, Decl(narrowDestructuredVariables.ts, 12, 2))
|
||||
>DataPrepared : Symbol(DataPrepared, Decl(narrowDestructuredVariables.ts, 2, 44))
|
||||
>DataPending : Symbol(DataPending, Decl(narrowDestructuredVariables.ts, 7, 2))
|
||||
|
||||
declare function isDataRefsPrepared(refs: ToRefs<Data>): refs is ToRefs<DataPrepared>;
|
||||
>isDataRefsPrepared : Symbol(isDataRefsPrepared, Decl(narrowDestructuredVariables.ts, 14, 39))
|
||||
>refs : Symbol(refs, Decl(narrowDestructuredVariables.ts, 16, 36))
|
||||
>ToRefs : Symbol(ToRefs, Decl(narrowDestructuredVariables.ts, 0, 32))
|
||||
>Data : Symbol(Data, Decl(narrowDestructuredVariables.ts, 12, 2))
|
||||
>refs : Symbol(refs, Decl(narrowDestructuredVariables.ts, 16, 36))
|
||||
>ToRefs : Symbol(ToRefs, Decl(narrowDestructuredVariables.ts, 0, 32))
|
||||
>DataPrepared : Symbol(DataPrepared, Decl(narrowDestructuredVariables.ts, 2, 44))
|
||||
|
||||
declare const data: Data;
|
||||
>data : Symbol(data, Decl(narrowDestructuredVariables.ts, 18, 13))
|
||||
>Data : Symbol(Data, Decl(narrowDestructuredVariables.ts, 12, 2))
|
||||
|
||||
const dataRefs = toRefs(data);
|
||||
>dataRefs : Symbol(dataRefs, Decl(narrowDestructuredVariables.ts, 19, 5))
|
||||
>toRefs : Symbol(toRefs, Decl(narrowDestructuredVariables.ts, 1, 47))
|
||||
>data : Symbol(data, Decl(narrowDestructuredVariables.ts, 18, 13))
|
||||
|
||||
const { prepared, payload } = dataRefs;
|
||||
>prepared : Symbol(prepared, Decl(narrowDestructuredVariables.ts, 20, 7))
|
||||
>payload : Symbol(payload, Decl(narrowDestructuredVariables.ts, 20, 17))
|
||||
>dataRefs : Symbol(dataRefs, Decl(narrowDestructuredVariables.ts, 19, 5))
|
||||
|
||||
if (prepared.current) {
|
||||
>prepared.current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18), Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
>prepared : Symbol(prepared, Decl(narrowDestructuredVariables.ts, 20, 7))
|
||||
>current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18), Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
|
||||
prepared.current;
|
||||
>prepared.current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
>prepared : Symbol(prepared, Decl(narrowDestructuredVariables.ts, 20, 7))
|
||||
>current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
|
||||
payload.current;
|
||||
>payload.current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18), Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
>payload : Symbol(payload, Decl(narrowDestructuredVariables.ts, 20, 17))
|
||||
>current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18), Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
|
||||
data.prepared;
|
||||
>data.prepared : Symbol(prepared, Decl(narrowDestructuredVariables.ts, 4, 24), Decl(narrowDestructuredVariables.ts, 9, 23))
|
||||
>data : Symbol(data, Decl(narrowDestructuredVariables.ts, 18, 13))
|
||||
>prepared : Symbol(prepared, Decl(narrowDestructuredVariables.ts, 4, 24), Decl(narrowDestructuredVariables.ts, 9, 23))
|
||||
|
||||
data.payload;
|
||||
>data.payload : Symbol(payload, Decl(narrowDestructuredVariables.ts, 5, 18), Decl(narrowDestructuredVariables.ts, 10, 19))
|
||||
>data : Symbol(data, Decl(narrowDestructuredVariables.ts, 18, 13))
|
||||
>payload : Symbol(payload, Decl(narrowDestructuredVariables.ts, 5, 18), Decl(narrowDestructuredVariables.ts, 10, 19))
|
||||
}
|
||||
|
||||
if (isDataRefsPrepared(dataRefs)) {
|
||||
>isDataRefsPrepared : Symbol(isDataRefsPrepared, Decl(narrowDestructuredVariables.ts, 14, 39))
|
||||
>dataRefs : Symbol(dataRefs, Decl(narrowDestructuredVariables.ts, 19, 5))
|
||||
|
||||
prepared.current;
|
||||
>prepared.current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
>prepared : Symbol(prepared, Decl(narrowDestructuredVariables.ts, 20, 7))
|
||||
>current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
|
||||
payload.current;
|
||||
>payload.current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
>payload : Symbol(payload, Decl(narrowDestructuredVariables.ts, 20, 17))
|
||||
>current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
|
||||
data.prepared;
|
||||
>data.prepared : Symbol(prepared, Decl(narrowDestructuredVariables.ts, 4, 24), Decl(narrowDestructuredVariables.ts, 9, 23))
|
||||
>data : Symbol(data, Decl(narrowDestructuredVariables.ts, 18, 13))
|
||||
>prepared : Symbol(prepared, Decl(narrowDestructuredVariables.ts, 4, 24), Decl(narrowDestructuredVariables.ts, 9, 23))
|
||||
|
||||
data.payload;
|
||||
>data.payload : Symbol(payload, Decl(narrowDestructuredVariables.ts, 5, 18), Decl(narrowDestructuredVariables.ts, 10, 19))
|
||||
>data : Symbol(data, Decl(narrowDestructuredVariables.ts, 18, 13))
|
||||
>payload : Symbol(payload, Decl(narrowDestructuredVariables.ts, 5, 18), Decl(narrowDestructuredVariables.ts, 10, 19))
|
||||
}
|
||||
|
||||
if (data.prepared) {
|
||||
>data.prepared : Symbol(prepared, Decl(narrowDestructuredVariables.ts, 4, 24), Decl(narrowDestructuredVariables.ts, 9, 23))
|
||||
>data : Symbol(data, Decl(narrowDestructuredVariables.ts, 18, 13))
|
||||
>prepared : Symbol(prepared, Decl(narrowDestructuredVariables.ts, 4, 24), Decl(narrowDestructuredVariables.ts, 9, 23))
|
||||
|
||||
prepared.current;
|
||||
>prepared.current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18), Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
>prepared : Symbol(prepared, Decl(narrowDestructuredVariables.ts, 20, 7))
|
||||
>current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18), Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
|
||||
payload.current;
|
||||
>payload.current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18), Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
>payload : Symbol(payload, Decl(narrowDestructuredVariables.ts, 20, 17))
|
||||
>current : Symbol(Ref.current, Decl(narrowDestructuredVariables.ts, 0, 18), Decl(narrowDestructuredVariables.ts, 0, 18))
|
||||
|
||||
data.prepared;
|
||||
>data.prepared : Symbol(DataPrepared.prepared, Decl(narrowDestructuredVariables.ts, 4, 24))
|
||||
>data : Symbol(data, Decl(narrowDestructuredVariables.ts, 18, 13))
|
||||
>prepared : Symbol(DataPrepared.prepared, Decl(narrowDestructuredVariables.ts, 4, 24))
|
||||
|
||||
data.payload;
|
||||
>data.payload : Symbol(DataPrepared.payload, Decl(narrowDestructuredVariables.ts, 5, 18))
|
||||
>data : Symbol(data, Decl(narrowDestructuredVariables.ts, 18, 13))
|
||||
>payload : Symbol(DataPrepared.payload, Decl(narrowDestructuredVariables.ts, 5, 18))
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
//// [tests/cases/compiler/narrowDestructuredVariables.ts] ////
|
||||
|
||||
=== narrowDestructuredVariables.ts ===
|
||||
interface Ref<T> { current: T };
|
||||
>current : T
|
||||
> : ^
|
||||
|
||||
type ToRefs<T> = { [K in keyof T]: Ref<T[K]> };
|
||||
>ToRefs : ToRefs<T>
|
||||
> : ^^^^^^^^^
|
||||
|
||||
declare function toRefs<T>(o: T): ToRefs<T>;
|
||||
>toRefs : <T>(o: T) => ToRefs<T>
|
||||
> : ^ ^^ ^^ ^^^^^
|
||||
>o : T
|
||||
> : ^
|
||||
|
||||
interface DataPrepared {
|
||||
prepared: true
|
||||
>prepared : true
|
||||
> : ^^^^
|
||||
>true : true
|
||||
> : ^^^^
|
||||
|
||||
payload: string
|
||||
>payload : string
|
||||
> : ^^^^^^
|
||||
|
||||
};
|
||||
|
||||
interface DataPending {
|
||||
prepared: false
|
||||
>prepared : false
|
||||
> : ^^^^^
|
||||
>false : false
|
||||
> : ^^^^^
|
||||
|
||||
payload: null
|
||||
>payload : null
|
||||
> : ^^^^
|
||||
|
||||
};
|
||||
|
||||
type Data = DataPrepared | DataPending;
|
||||
>Data : Data
|
||||
> : ^^^^
|
||||
|
||||
declare function isDataRefsPrepared(refs: ToRefs<Data>): refs is ToRefs<DataPrepared>;
|
||||
>isDataRefsPrepared : (refs: ToRefs<Data>) => refs is ToRefs<DataPrepared>
|
||||
> : ^ ^^ ^^^^^
|
||||
>refs : ToRefs<Data>
|
||||
> : ^^^^^^^^^^^^
|
||||
|
||||
declare const data: Data;
|
||||
>data : Data
|
||||
> : ^^^^
|
||||
|
||||
const dataRefs = toRefs(data);
|
||||
>dataRefs : ToRefs<Data>
|
||||
> : ^^^^^^^^^^^^
|
||||
>toRefs(data) : ToRefs<Data>
|
||||
> : ^^^^^^^^^^^^
|
||||
>toRefs : <T>(o: T) => ToRefs<T>
|
||||
> : ^ ^^ ^^ ^^^^^
|
||||
>data : Data
|
||||
> : ^^^^
|
||||
|
||||
const { prepared, payload } = dataRefs;
|
||||
>prepared : Ref<true> | Ref<false>
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^
|
||||
>payload : Ref<string> | Ref<null>
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>dataRefs : ToRefs<Data>
|
||||
> : ^^^^^^^^^^^^
|
||||
|
||||
if (prepared.current) {
|
||||
>prepared.current : boolean
|
||||
> : ^^^^^^^
|
||||
>prepared : Ref<true> | Ref<false>
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^
|
||||
>current : boolean
|
||||
> : ^^^^^^^
|
||||
|
||||
prepared.current;
|
||||
>prepared.current : true
|
||||
> : ^^^^
|
||||
>prepared : Ref<true>
|
||||
> : ^^^^^^^^^
|
||||
>current : true
|
||||
> : ^^^^
|
||||
|
||||
payload.current;
|
||||
>payload.current : string | null
|
||||
> : ^^^^^^^^^^^^^
|
||||
>payload : Ref<string> | Ref<null>
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>current : string | null
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
data.prepared;
|
||||
>data.prepared : boolean
|
||||
> : ^^^^^^^
|
||||
>data : Data
|
||||
> : ^^^^
|
||||
>prepared : boolean
|
||||
> : ^^^^^^^
|
||||
|
||||
data.payload;
|
||||
>data.payload : string | null
|
||||
> : ^^^^^^^^^^^^^
|
||||
>data : Data
|
||||
> : ^^^^
|
||||
>payload : string | null
|
||||
> : ^^^^^^^^^^^^^
|
||||
}
|
||||
|
||||
if (isDataRefsPrepared(dataRefs)) {
|
||||
>isDataRefsPrepared(dataRefs) : boolean
|
||||
> : ^^^^^^^
|
||||
>isDataRefsPrepared : (refs: ToRefs<Data>) => refs is ToRefs<DataPrepared>
|
||||
> : ^ ^^ ^^^^^
|
||||
>dataRefs : ToRefs<Data>
|
||||
> : ^^^^^^^^^^^^
|
||||
|
||||
prepared.current;
|
||||
>prepared.current : true
|
||||
> : ^^^^
|
||||
>prepared : Ref<true>
|
||||
> : ^^^^^^^^^
|
||||
>current : true
|
||||
> : ^^^^
|
||||
|
||||
payload.current;
|
||||
>payload.current : string
|
||||
> : ^^^^^^
|
||||
>payload : Ref<string>
|
||||
> : ^^^^^^^^^^^
|
||||
>current : string
|
||||
> : ^^^^^^
|
||||
|
||||
data.prepared;
|
||||
>data.prepared : boolean
|
||||
> : ^^^^^^^
|
||||
>data : Data
|
||||
> : ^^^^
|
||||
>prepared : boolean
|
||||
> : ^^^^^^^
|
||||
|
||||
data.payload;
|
||||
>data.payload : string | null
|
||||
> : ^^^^^^^^^^^^^
|
||||
>data : Data
|
||||
> : ^^^^
|
||||
>payload : string | null
|
||||
> : ^^^^^^^^^^^^^
|
||||
}
|
||||
|
||||
if (data.prepared) {
|
||||
>data.prepared : boolean
|
||||
> : ^^^^^^^
|
||||
>data : Data
|
||||
> : ^^^^
|
||||
>prepared : boolean
|
||||
> : ^^^^^^^
|
||||
|
||||
prepared.current;
|
||||
>prepared.current : boolean
|
||||
> : ^^^^^^^
|
||||
>prepared : Ref<true> | Ref<false>
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^
|
||||
>current : boolean
|
||||
> : ^^^^^^^
|
||||
|
||||
payload.current;
|
||||
>payload.current : string | null
|
||||
> : ^^^^^^^^^^^^^
|
||||
>payload : Ref<string> | Ref<null>
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>current : string | null
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
data.prepared;
|
||||
>data.prepared : true
|
||||
> : ^^^^
|
||||
>data : DataPrepared
|
||||
> : ^^^^^^^^^^^^
|
||||
>prepared : true
|
||||
> : ^^^^
|
||||
|
||||
data.payload;
|
||||
>data.payload : string
|
||||
> : ^^^^^^
|
||||
>data : DataPrepared
|
||||
> : ^^^^^^^^^^^^
|
||||
>payload : string
|
||||
> : ^^^^^^
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// @strict: true
|
||||
// @target: es2015
|
||||
|
||||
interface Ref<T> { current: T };
|
||||
type ToRefs<T> = { [K in keyof T]: Ref<T[K]> };
|
||||
declare function toRefs<T>(o: T): ToRefs<T>;
|
||||
|
||||
interface DataPrepared {
|
||||
prepared: true
|
||||
payload: string
|
||||
};
|
||||
|
||||
interface DataPending {
|
||||
prepared: false
|
||||
payload: null
|
||||
};
|
||||
|
||||
type Data = DataPrepared | DataPending;
|
||||
|
||||
declare function isDataRefsPrepared(refs: ToRefs<Data>): refs is ToRefs<DataPrepared>;
|
||||
|
||||
declare const data: Data;
|
||||
const dataRefs = toRefs(data);
|
||||
const { prepared, payload } = dataRefs;
|
||||
|
||||
if (prepared.current) {
|
||||
prepared.current;
|
||||
payload.current;
|
||||
data.prepared;
|
||||
data.payload;
|
||||
}
|
||||
|
||||
if (isDataRefsPrepared(dataRefs)) {
|
||||
prepared.current;
|
||||
payload.current;
|
||||
data.prepared;
|
||||
data.payload;
|
||||
}
|
||||
|
||||
if (data.prepared) {
|
||||
prepared.current;
|
||||
payload.current;
|
||||
data.prepared;
|
||||
data.payload;
|
||||
}
|
Загрузка…
Ссылка в новой задаче