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

[bug] TemplateStringsArray is incompatible with literal array type #16552

Open
ForbesLindesay opened this issue Jun 15, 2017 · 7 comments
Open
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@ForbesLindesay
Copy link
Contributor

TypeScript Version: 2.4.0

Code

// A *self-contained* demonstration of the problem follows...
interface SQLQuery<TResult> {
  __result: TResult;
} 
declare function sql(
  literals: ['SELECT id FROM users'],
  ...placeholders: any[]
): SQLQuery<{id: number}>;

declare function querySync<TResult>(q: SQLQuery<TResult>): Array<TResult>;

const values: Array<{id: number}> = querySync(sql`SELECT id FROM users`);

Expected behavior:

Typescript should see that the input string 'SELECT id FROM users' matches the expected literals of ['SELECT id FROM users'] and use the declared function, allowing me to generate an overloaded version of the sql function for each query.

Actual behavior:

I get the error:

src/index.ts(23,50): error TS2345: Argument of type 'TemplateStringsArray' is not assignable to parameter of type '["SELECT id FROM users"]'.
Property '0' is missing in type 'TemplateStringsArray'.

@DanielRosenwasser DanielRosenwasser added the Bug A bug in TypeScript label Jun 16, 2017
@DanielRosenwasser
Copy link
Member

I think this is contingent on #16592.

@DanielRosenwasser DanielRosenwasser added Suggestion An idea for TypeScript and removed Bug A bug in TypeScript labels Jun 16, 2017
@DanielRosenwasser
Copy link
Member

Actually, I don't know if this will work even with the changes I have in mind. TemplateStringsArray is effectively a ReadonlyArray<string> - but you can't assign a ReadonlyArray to a mutable Array. So at the minimum you'd have to write something like

interface MyCustomType extends TemplateStringsArray {
  0: "SELECT id FROM users"
}

@ForbesLindesay
Copy link
Contributor Author

That would be fine. I'm going to be auto-generating these definitions anyway, by parsing the code to see which functions are called. This would be very much a workaround for #16551.

At the moment, that doesn't seem to work either though.

@pablobirukov
Copy link

declare function id<T extends string>(list: Array<T>): Array<T>;
declare function readonlyId<T extends string>(list: ReadonlyArray<T>): ReadonlyArray<T>;

type LiteralType = "foo" | "bar";

const array: Array<LiteralType> = [];
const readonlyArray: ReadonlyArray<LiteralType> = [];

const foo: ReadonlyArray<LiteralType> = id(array);
const bar: ReadonlyArray<LiteralType> = readonlyId(array);
//    ~~~
// Type 'ReadonlyArray<string>' is not assignable to type 'ReadonlyArray<LiteralType>'.
//  Type 'string' is not assignable to type 'LiteralType'.const bar: ReadonlyArray<LiteralType>
const baz: ReadonlyArray<LiteralType> = readonlyId(readonlyArray);

Isn't it a bug that generic type information is being lost when ReadonlyArray is assigned to Array?

@ForbesLindesay
Copy link
Contributor Author

@R00GER that looks like a separate bug, it should probably have its own issue.

@RyanCavanaugh
Copy link
Member

@DanielRosenwasser can you give an update on next steps here?

@weswigham weswigham added the In Discussion Not yet reached consensus label Nov 6, 2018
@xialvjun
Copy link

There shouldn't be a type TemplateStringsArray, it should be a const string tuple type, so we can write code:

interface SQL<TSA, VS> {
  texts: TSA;
  values: VS;
}

function sql<TSA extends readonly string[], VS extends any[]>(texts:TSA, ...values: VS): SQL<TSA, VS> {
  return { texts, values };
}

// then
let s: SQL<['select * from person where a=', ' and b=', ''], [number, Date]> = sql`select * from person where a=${1} and b=${new Date()}`;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

6 participants