0

I have got error TS2322: Type 'string' is not assignable to type 'never'. in result[key] = forms.${key};

and don't understand how i can fix it. (without prefix everything is ok). Why typescript considers result[key] as never?

export const InitialState = {
  login: {
    login: '',
    password: '',
    accept_terms: false,
  },
  forgot: {
    login: '',
    password: '',
  },
};

type FormsKey = keyof typeof InitialState;

type FormsMap = {
  [K in FormsKey]: `forms.${K}`
};

const keys = Object.keys(InitialState) as FormsKey[];
const forms: FormsMap = keys.reduce<FormsMap>((result, key) => {
  result[key] = `forms.${key}`;
  return result;
}, {} as FormsMap);

export default forms;

2 Answers2

0

Because of const forms: FormsMap = keys.reduce<FormsMap>((result, key) => { typescript undesturd result[key] as a undefined possibility, e.g. if you find an unknow key , thats return never, if you have a defined explicit keys, you should create a type or enum for match for this key. Otherise I suggest you avoid set value in array, insteread you use an Map type for this.

vfbraton
  • 83
  • 1
  • 6
  • but typescript know what `key` is `keyof of InitialState`. So obviosly `result[key]` exist in `FormsMap` – Valerii Zubkov Jun 20 '22 at 21:46
  • >Otherise I suggest you avoid set value in array, insteread you use an Map type for this. < Are you speaking about `keys` array? – Valerii Zubkov Jun 20 '22 at 21:47
  • No i speaking about Map object for find specific key. 'but typescript know what key is keyof of InitialState. So obviosly result[key] exist in FormsMap ' -> in this case initialState is an object and not have explicit type, so it's is a ```any``` type, and ```any``` is a never equivalent. you should try write type definition for InitialState, something like ``` type InitialStateType = { login: {login: string , password: string, accepted_terms: boolean} forgot: { login: string, password: password, }, } ``` – vfbraton Jun 21 '22 at 00:11
  • And i assumed to you try inplement form and login global state in react or something like , I suggest you separate form state f=from login state, using things like custonhooks or redux – vfbraton Jun 21 '22 at 00:12
  • not `initialState` not any. you can check it. – Valerii Zubkov Jun 21 '22 at 08:56
  • >not initialState not any. you can check it but if you need to use key for read, you should need define type for object. Just try. just another thing ````type FormsMap = { [K in keyof T]: K extends string ? `forms.${K}` : never } ```` maybe extract key as a string type cause this, because key extract not work like this – vfbraton Jun 22 '22 at 03:01
0
export const InitialState = {
  login: {
    login: '',
    password: '',
    accept_terms: false,
  },
  forgot: {
    login: '',
    password: '',
  },
}

type FormsMap<T> = {
  [K in keyof T]: K extends string ? `forms.${K}` : never
}

const getForms = <T>(state: T) => {
  const result: Record<string, any> = {}
  Object.entries(state).forEach(([key]) => {
    result[key] = `forms.${key}`
  })
  return result as FormsMap<T>
}

const forms = getForms(InitialState)
// type forms = {
//   forgot: "forms.forgot"
//   login: "forms.login"
// }

export default forms
Kiritushka
  • 770
  • 1
  • 6
  • 11
  • intresting solution, but types `getForms` doen't work well, because we just mark Record as FormsMap, but there isn't any check by types. for example `result[key] = 'notForms'` - is ok in this code. – Valerii Zubkov Jun 21 '22 at 09:04