#Better utility to test for an object

41 messages · Page 1 of 1 (latest)

digital tendon
#

I wonder what do you folks think is the best way to check for an object. I reckon these objects:

  1. {}
  2. {foo: string}
    and these - not:
  3. () => 1
  4. number[]
  5. {foo: string}[]

Do you think this would be most reasonable:

type IsObject<T> = T extends object
  ? T extends any[]
    ? false
    : T extends Function
    ? false
    : true
  : false;
#

i.e. arrays and functions are not objects. Every other object objects - are

#

Am I missing something?

worn baneBOT
#
onkeltem#0

Preview:```ts
type IsObject<T> = T extends object
? T extends any[]
? false
: T extends Function
? false
: true
: false

interface Iface {
name: string
age: number
}

// prettier-ignore
type Tests = [
a: IsObject<undefined>,
//^?
b: IsObject<null>,
...```

quartz meteor
#

What's the purpose of this type?

#

FYI, {} does not mean object, it means "anything that can have properties."

digital tendon
#

But it returns true...

#

Oh, wait

#
const emptyObj = {}
  h: IsObject<typeof emptyObj>,
//^? true
quartz meteor
#

42 can have properties too, like .toString, so 42 is also a {}.

digital tendon
#

I don't know, maybe I'n doing something wrong

worn baneBOT
#
const foo: {} = 42
// no compile error
digital tendon
#

The purpose is to traverse a tree and build an object with keys flattened

quartz meteor
#

I mean, technically it isn't wrong to have root.num.toFixed or root.func.name.

digital tendon
quartz meteor
worn baneBOT
#
nonspicyburrito#0

Preview:```ts
type IsObject<T> = T extends object
? T extends any[]
? false
: T extends Function
? false
: true
: false

interface Iface {
name: string
age: number
}

// prettier-ignore
type Tests = [
a: IsObject<undefined>,
//^?
b: IsObject<null>,
...```

quartz meteor
#

See the example at the bottom.

digital tendon
#

cheating! haha

quartz meteor
#

Realistically, you should just define what you want to happen, and write the type according to that.

#

If you define "if it's an array, then keys like .length/.map/etc aren't allow" and you just write your type according to that.

digital tendon
#

I agree with that. In reality I need to distinguish just scalars, arrays and objects

#

Because I need to make from this:

type Person = {
  name?: string;
  education?: {
    university: string;
    graduatedAt: string;
  };
  children: {
    name: string;
    age: number;
  }[];
}

this:

const personFieldTitles: FieldTitles = {
  "name": "Name",
  "education": "Education",
  "education.university": "adsad",
  "education.graduatedAt": "asdd",
  "children": "Children",
  "children.name": "Child name",
  "children.age": "Child age",
};
quartz meteor
#

Yeah I'd suggest writing down the rules and test cases, then start implementing.

digital tendon
#

I used an example from another thread and am currently trying to come up with somethign reasonable

quartz meteor
#

I think there's also a snippet in the server.

#

!:auto-path

#

Hmm.

#

!:autopath

worn baneBOT
#
tjjfvi#0

Preview:```ts
...
type User = {
id: string,
name: string,
age: number,
friends: User[],
parents: [User, User],
}

get(user, "friends.0") // returns User
get(user, "friends.0.age") // returns number
get(user, "this.does.not.exist") // error
get(user, "parents.3") // error, out of bounds

getString(user, "friends.0.id") // returns string
getString(user, "friends.0.age") // error, not a string```

digital tendon
#

Thanks. There are many approaches, of them I have been thinking for a weak

#

I'm currently trying to work around arrays to flatten their items like they were no array at all

#

i.e. friends: User[] should become just friends: User

#

Because I need it to give field titles

quartz meteor
#

That seems like you can just use X extends infer T[] ? T : ....

digital tendon
#

yep, I'm doing something like that. A little confusing, still working

worn baneBOT
#
onkeltem#0

Preview:```ts
export type Scalar =
| string
| number
| boolean
| symbol
| bigint

type IsObject<T> = T extends object
? T extends any[]
? false
: T extends Function
? false
: true
: false

type Flatten<
T,
P extends string = ""

= T extends (infer Item)[
...```

digital tendon
#

It won't support arrays of mixed objects but that's ok

#

I need to come up with a way to describe API objects

#

I plan to extends API generation from OpenAPI specs to gnerate not only Typescript but JS as well

#

with reasonable set of formatters for every field and a title