MDA
MDA

Reputation: 113

extract key of object from a dynamic typed object

I have this interface:

interface test {
   [key: string]: string
}

and this object:

const obj: test ={
   name: 'mda',
   telephone: '1234'
}

now when i want to use this obj in variable the intellisense not working for this object. in other word i can choose a key that it does not exist in object.

const myName = obj.ndfnasdfn

and compiler not show error for this key. this is playground area: playground

update to a nested object : for this nested object what is solution: i use @Titian Cernicova-Dragomir solutin for the nested object in below but the compiler does not show error.

interface test {
[key: string]: string
 }

 function createTest<T extends test>(o: T) {
     return o;
 }
 interface state {
     test1: test,
     test2:test
 }
 const state: state = {
    test1:createTest({
        t1:'m',
        t2:'e'
  }),
  test2: createTest({
    t3:'sss'
     })
  }
 const {test1, test2} = state
 const t1 = test1.sdfsafsdf //no error

playground

update 2: if we don't use the createTest function so we get the purpose as we don't specify type to state like this playground

my answer was that i use type for state and get a compiler error for the keys that they don't exist in test1

Upvotes: 1

Views: 101

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249506

If you specify the type of the variable explicitly, as you have, that will be the final type of the variable, the compiler will to infer anything extra for the variable.

If you want to let the compiler infer the type just remove the annotation

const obj ={
   name: 'mda',
   telephone: '1234'
}

If you want to constrain the variable to have only string values, you will need to use a function to constrain the type but let the compiler still infer the type:

interface test {
    [key: string]: string
}

function createTest<T extends test>(o: T) {
    return o;
}

const obj = createTest({
    name: 'mda',
    telephone: '1234'
    // age: 10 // error not a string
});
obj.name //ok
obj.sss //error

Playground link

For your nested sample, you will need a function to create state not just test. The same principle applies, if you explicitly specify the type of test1 and test2 that will be the final type regardless of the type createTest will return.

interface test {
    [key: string]: string
}

interface state {
    test1: test,
    test2:test
}
function createTest<T extends state>(o: T) {
    return o;
}
const state = createTest({
    test1: {
        t1: 'm',
        t2: 'e'
    },
    test2: {
        t3: 'sss'
    }
});
const {test1, test2} = state
const t1 = test1.sdfsafsdf //error

Playground link

Upvotes: 2

Related Questions