Тип ‘IConnectionState’ не может быть присвоен типу ‘{connected: false; тип: «none»; }’

#reactjs #typescript #recoiljs

#reactjs #машинописный текст #recoiljs

Вопрос:

Итак, я думаю, что у моего линтера typescrpt короткое замыкание, потому что я ни за что на свете не могу понять, почему продолжает возникать эта ошибка линтинга.

 Type 'IConnectionState' is not assignable to type '{ connected: false; type: "none"; }'
 

Ниже приведен мой код, который, как вы можете ясно видеть, не должен иметь никаких последствий.

 
export interface IConnectionState {
    connected: boolean;
    type: 'none' | 'player' | 'host';
}

export const ConnectionState: RecoilState<IConnectionState> = atom({
    key: 'connectionState',
    default: {
        connected: false,
        type: 'none'
    }
});

 

Если это поможет, я использую отдачу. Но, глядя на типы отдачи, RecoilState should type принимает подтип default значения, присвоенного его объекту options .

Я так растерялась.

Ответ №1:

Я вижу аналогичную проблему с более простым интерфейсом.

 export const myState: RecoilState<boolean> = atom({
  key: 'myState',
  default: false,
});

// Type '<RecoilState<false>' is not assignable to type 'RecoilState<boolean>'.
 

Я могу это исправить, либо объявив default: false as boolean , либо, что, вероятно, лучше, добавив generic <T> в вызов метода:

 export const myState: RecoilState<boolean> = atom<boolean>({
  key: 'myState',
  default: false,
});
 

Или вы можете полностью исключить объявления типов, и TypeScript вычислит это.

Ответ №2:

На самом деле линтер работает так, как ожидалось. Вы устанавливаете тип ConnectionState to be IConnectionState , но вы никогда не включаете свойство key в интерфейс.

Интерфейс IConnectionState правильный, но он должен быть вложен в другой интерфейс.

 const NONE = 'none';
const PLAYER = 'player';
const HOST = 'host';
const CONNECTIONSTATE = "connectionState";

type TType = typeof NONE | typeof PLAYER | typeof HOST;

interface IConnectionStateDefault {
    connected: boolean;
    type: TType
}

interface IConnectionState {
    key: typeof CONNECTIONSTATE,
    default: IConnectionStateDefault
}


export const ConnectionState: RecoilState<IConnectionState> = atom({
    key: "connectionState",
    default: {
        connected: false,
        type: 'none'
    }
});
 

Если IConnectionState у него больше key значений, просто сделайте то же самое, что и я, с TType тем, где вы формируете объединение по возможным типам, которые key могут существовать как.

Ответ №3:

Это то, что я делал в нашем monorepo.
Создайте глобальный файл для ВСЕХ ключей, чтобы попытаться сохранить понимание того, что вы не хотите никаких столкновений, поскольку существует один реестр Recoil.

 export enum GlobalRecoilKeyEnum {
     ATOM_SOME_BOOLEAN_KEY= "ATOM_SOME_BOOLEAN_KEY",
}
 

Создайте региональный файл атомов (Nx позволяет мне изолировать доступ с помощью linting.)

 export const SomeBooleanAtom = atom({
    key: GlobalRecoilKeyEnum.ATOM_SOME_BOOLEAN_KEY,
    default: false
});
 

Способы доступа к функциональным компонентам.

 const isSomeBoolean: boolean = useRecoilValue<boolean>(SomeBooleanAtom);
const setSomeBoolean: SetterOrUpdater<boolean> = useSetRecoilState<boolean>(SomeBooleanAtom);
const [isPractice, setSomeBoolean]: [boolean, SetterOrUpdater<boolean>] = useRecoilValue<boolean>(SomeBooleanAtom);