简体   繁体   中英

How to assign types of (typeof) all elements in the object to a variable in JavaScript | Typescript?

I have a javascript object that looks like

I am trying to assign types of all the elements in the object to a variable where I am facing the issue,

whereas I am able to assign it when I mention the constants separately instead of using it them in an object in the second code snippet

 const a = Object.freeze({ REMOVE_ITEM:'REMOVE_ITEM' ADD_ITEM:'ADD_ITEM' }); //How to assign the types of all elements in the above object const b = typeof ? // All Properties in the above object ((Facing Problem Here)); //I Can do it if const REMOVE_ITEM ='REMOVE_ITEM'; const ADD_ITEM = 'ADD_ITEM'; const b = typeof REMOVE_ITEM | typeof ADD_ITEM;

You can use TypeScripts as const notation ( found here ).

const a = Object.freeze({
  REMOVE_ITEM: 'REMOVE_ITEM',
  ADD_ITEM: 'ADD_ITEM'
} as const);

// assign typeof 
const b: typeof a = {} as any; // you can ignore `{} as any` - only here for example

b; // type is { REMOVE_ITEM: 'REMOVE_ITEM', ADD_ITEM: 'ADD_ITEM' }
b.REMOVE_ITEM; // = 'REMOVE_ITEM'
b.ADD_ITEM; // = 'ADD_ITEM'

// destructure
const { REMOVE_ITEM, ADD_ITEM } = a;

REMOVE_ITEM; // = 'REMOVE_ITEM'
ADD_ITEM; // = 'ADD_ITEM'

Here is a stackblitz so you can see the types in action.

As I understood you, you are trying to export a type to make use of it in another file. This is quite easy:

File with your type definition (myType.ts / myType.d.ts):

export type MyType = {
  foo: boolean
  bar: 'foo' | 'bar' 
}

File where you want to use that type:

import { MyType } from './myType' // should be in the same folder, otherwise correct the path

const myVar: MyType = false // error
const myVar: MyType = { foo: false, bar: 'foo' } //working

You can not define any types during the runtime since types will be removed while transpiling. But you can define an enum and use it to define your types:

enum MyEnum {
  FOO_BAR = 'foo_bar',
  LORD_OF = 'the_rings'
}
type MyOhterType = {
  fooBar: MyEnum
}

const myOtherVar: MyOtherType = {
  fooBar: MyEnum.FOO_BAR
}

Looks like you are mixing JavaScript's typeof operator with TypeScript's - both do not accomplish the same thing.

In JS, typeof something will evaluate to a simple runtime string (such as 'number' , 'string' , 'object' ...) which your app can then use for comparison purposes. This is not what you want here.

In TS, typeof helps you extract the implied TS type out of a JS variable, as a meaningful structure - a true TypeScript type . This is helpful when you want to define complex TS types out of existing JS code.

const a = Object.freeze({
  REMOVE_ITEM: 'REMOVE_ITEM',
  ADD_ITEM: 'ADD_ITEM'
});

// ^ to TypeScript, this is similar to this type:
// Readonly<{ REMOVE_ITEM: string; ADD_ITEM: string; }>

To extract its implied type:

type AObject = typeof a;
// Readonly<{ REMOVE_ITEM: string; ADD_ITEM: string; }>

To have type definitions matching the keys in that object, use keyof when defining your TS type matching any key:

type AKey = keyof AObject;
// "REMOVE_ITEM" | "ADD_ITEM"

// or in a strictly similar way:

type AKey = keyof typeof a;
// "REMOVE_ITEM" | "ADD_ITEM"

Now, back to runtime code. Once you have extracted the AKey type matching the keys of a , you can enforce type consistency for some JS values and arguments where needed:

function createActionObject(actionType: AKey) {
  return { type: actionType };
}

const action1 = createActionObject('REMOVE_ITEM');
// compiles and works as expected

const action2 = createActionObject('SOME_BAD_KEYNAME');
// TypeScript Error ->
// Type '"SOME_BAD_KEYNAME"' is not assignable to type '"REMOVE_ITEM" | "ADD_ITEM"'

Finally , you cannot "assign" TS types to a JS variable, you can merely describe what a JS variable needs to look like so TypeScript validates it before eventually transpiling to JS. If you tried to get an array that lists all keys in a , you need to use traditional JS methods:

const b = Object.keys(a);
// to JavaScript: will be ['REMOVE_ITEM', 'ADD_ITEM']
// to TypeScript: string[]

// or, to get stronger typings for `b` rather than just `string[]`:

const b = Object.keys(a) as (keyof typeof a)[];
// to JavaScript: will be ['REMOVE_ITEM', 'ADD_ITEM']
// to TypeScript: ('REMOVE_ITEM' | 'ADD_ITEM')[]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM