Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect types for Payload #6

Closed
cre8 opened this issue Nov 27, 2023 · 3 comments
Closed

Incorrect types for Payload #6

cre8 opened this issue Nov 27, 2023 · 3 comments

Comments

@cre8
Copy link

cre8 commented Nov 27, 2023

I moved the create function into a class because I need to define the signer dynamic at runtime like

  async create<Payload extends Record<string, unknown>>(
    payload: Payload,
    disclosureFrame: DisclosureFrame<Payload>
  ): Promise<SdJwt> {
    const sdJwt = new SdJwt<JWTHeader, Payload>(
      {
        header: {
          alg: SignatureAndEncryptionAlgorithm.EdDSA,
          typ: 'sd-jwt',
        },
        payload: payload,
      },
      {
        saltGenerator,
        signer: this.getSigner.bind(this),
        hasherAndAlgorithm,
        disclosureFrame,
      }
    );
    return sdJwt;
  }

But when I call it I get different errors:

export interface Foo {
  name: string;
  [key: string]: any;
}

const sdJwt = await SdJWTCreator.create(agent);
sdJwt.create<Foo>({ name: 'Mirko' }, { name: true, __decoyCount: 2 });

This will throw an error for name: Type 'string' is not assignable to type 'boolean | undefined'.ts(2322)

When I remove the [key: string]: any definition from my interface, it throws: Type 'Foo' does not satisfy the constraint 'Record<string, unknown>'. Index signature for type 'string' is missing in type 'Foo'.

I think I am defining the types wrong when transforming the examples to a class based approach. An example of it in the code folder would help a lot! :)

@berendsliedrecht
Copy link
Owner

Are you on the latest version? My code succeeds when I try to recreate your example:

import {
  DisclosureFrame,
  HasherAlgorithm,
  SdJwt,
  SignatureAndEncryptionAlgorithm,
} from "jwt-sd";

type JWTHeader = {
  alg: string;
  typ: string;
};

function create<Payload extends Record<string, unknown>>(
  payload: Payload,
  disclosureFrame: DisclosureFrame<Payload>
): Promise<SdJwt<JWTHeader, Payload>> {
  const sdJwt = new SdJwt<JWTHeader, Payload>(
    {
      header: {
        alg: SignatureAndEncryptionAlgorithm.EdDSA,
        typ: "sd-jwt",
      },
      payload: payload,
    },
    {
      saltGenerator: () => "salt",
      signer: () => new Uint8Array(32).fill(42),
      hasherAndAlgorithm: {
        algorithm: HasherAlgorithm.Sha256,
        hasher: () => new Uint8Array(32).fill(32),
      },
      disclosureFrame,
    }
  );
  return Promise.resolve(sdJwt);
}

type Foo = {
  foo: string;
};

create<Foo>({ foo: "hi!" }, { foo: true, __decoyCount: 2 }).then(console.log)

output:

jwt-sd-demo λ npx ts-node index.ts
SdJwt {
  header: { alg: 'EdDSA', typ: 'sd-jwt' },
  payload: { foo: 'hi!' },
  signature: undefined,
  signer: [Function: signer],
  disclosures: undefined,
  keyBinding: undefined,
  hasherAndAlgorithm: { algorithm: 'sha-256', hasher: [Function: hasher] },
  saltGenerator: [Function: saltGenerator],
  disclosureFrame: { foo: true, __decoyCount: 2 }
}

@berendsliedrecht
Copy link
Owner

berendsliedrecht commented Nov 27, 2023

Ahhh I see. You are using an interface and not a type.

A type in typescript extends Record<string, unknown> (or {[key: string]: unknown}), but an interface does not. If you swap the Foo to a type, it will work.

Or, you do not define the type Foo and TypeScript will infer the generic of the object you passed in.

create({ foo: "hi!" }, { foo: true, __decoyCount: 1 }).then(console.log);

This has full type completion on the disclosureframe even if Foo is not supplied.

to make the interface with [key: string]: unknown work, I would have to dive into the disclosure frame typing, but for now I'd just suggest to make it a type.

@cre8
Copy link
Author

cre8 commented Dec 5, 2023

@berendsliedrecht Ty very much :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants